Veritas Kanban

June 3, 2026 · View on GitHub

Version: 3.4.0
Last Updated: 2026-03-08
Base URL: http://localhost:3001/api
Canonical prefix: /api/v1 (alias: /api)

This is the source-of-truth companion to the Swagger/OpenAPI spec. For workflow-engine-specific endpoints, see API-WORKFLOWS.md.


Table of Contents

  1. Authentication
  2. Base URLs & Environments
  3. Error Model
  4. Tasks
  5. Time Tracking
  6. Observations
  7. Analytics
  8. Configuration
  9. Settings
  10. Lifecycle Hooks
  11. Chat & Squad
  12. Agent Status
  13. Auth & Diagnostics
  14. Identity & Workspaces
  15. Telemetry
  16. Health
  17. WebSocket
  18. Task Verification
  19. Task Comments
  20. Task Subtasks
  21. Task Deliverables
  22. Task Archive
  23. Attachments
  24. Agent Permissions
  25. Agent Routing
  26. Shared Resources
  27. Doc Freshness
  28. Cost Prediction
  29. Error Learning
  30. Tool Policies
  31. Traces
  32. Audit
  33. Common Workflows
  34. Versioning & Deprecation
  35. Rate Limits
  36. Additional Endpoint Groups

Authentication

VK supports three authentication methods. All are optional when running locally with VERITAS_AUTH_ENABLED=false.

Methods

MethodHeader / ParamUse Case
Bearer Token (JWT)Authorization: Bearer <token>Browser sessions, UI login
API KeyX-API-Key: <key>Agent integrations, scripts
Device SessionAuthorization: Bearer vk_dev_…Paired desktop/mobile/PWA clients
WS Query Paramws://host:port/ws?api_key=<key>WebSocket connections

Roles

RolePermissions
adminFull access — all endpoints, destructive operations, deep health
agentRead/write tasks, time tracking, observations, chat, telemetry
read-onlyRead-only access to all GET endpoints

v5 Permission Context

Protected REST handlers and WebSocket connections receive a shared auth context: role, userId, workspaceId, actorType, authMethod, tokenName, and role-derived permissions. Device sessions also include deviceSessionId, deviceId, clientId, clientMode, capabilities, and degradedReason when a current workspace role downgrade trimmed the approved scopes. Existing endpoints still accept the compatibility roles above, but new v5 route work should declare the specific permission it requires, such as task:read, task:write, workflow:execute, or admin:manage.

Localhost Bypass

When VERITAS_AUTH_LOCALHOST_BYPASS=true, requests from 127.0.0.1 / ::1 are authenticated automatically with the role set by VERITAS_AUTH_LOCALHOST_ROLE (default: read-only).

API Key Configuration

Set via environment:

# Admin key
VERITAS_ADMIN_KEY=your-admin-key

# Additional keys (format: name:key:role, comma-separated)
VERITAS_API_KEYS=agent1:key123:agent,readonly:key456:read-only

Base URLs & Environments

EnvironmentBase URLNotes
Local devhttp://localhost:3001/apiDefault port
ProductionDeploy behind reverse proxy with TLSAdd rate limiting externally

Both /api/v1/... and /api/... resolve to the same handlers. Use /api for brevity.


Error Model

All errors return a consistent JSON envelope:

{
  "error": "Human-readable message",
  "code": "OPTIONAL_ERROR_CODE",
  "details": {}
}

Status Codes

CodeMeaning
200Success
201Created
400Bad request — invalid body, missing fields
401Not authenticated
403Forbidden — insufficient role
404Resource not found
409Conflict — duplicate, state violation, stale revision
429Rate limited
503Service degraded (health checks)

Tasks

All task routes are mounted at /api/tasks.

Task Revisions and Conflict Handling

Task reads and writes include optimistic-concurrency metadata:

  • GET /api/tasks/:id, POST /api/tasks, and successful task mutations return ETag: "task:<taskId>:<revision>".
  • The same revision is also returned as X-Resource-Revision.
  • Clients that edit a loaded task should send If-Match with the last ETag, or X-Resource-Revision with the last numeric revision.
  • Tasks include revision, createdBy, and updatedBy. Comments include revision, createdBy, and updatedBy when created or edited through the v5 routes.

When the supplied revision is stale, the API returns 409 CONFLICT and includes the latest resource so the client can reload or reapply the edit:

{
  "code": "CONFLICT",
  "message": "task task_20260531_abcd has changed since it was loaded. Reload and retry with the latest revision.",
  "details": {
    "resourceType": "task",
    "resourceId": "task_20260531_abcd",
    "expectedRevision": 3,
    "currentRevision": 4,
    "current": {
      "id": "task_20260531_abcd",
      "title": "Latest task title",
      "revision": 4
    }
  }
}

List Tasks

GET /api/tasks

Returns all active tasks. Supports query filters.

Response 200:

{
  "tasks": [
    {
      "id": "TASK-001",
      "title": "Implement login",
      "status": "in-progress",
      "priority": "high",
      "project": "rubicon",
      "assignee": "agent-1",
      "createdAt": "2026-03-01T10:00:00Z"
    }
  ]
}

Get Task Counts

GET /api/tasks/counts

Returns task counts grouped by status.

Create Task

POST /api/tasks

Body:

{
  "title": "Fix auth bug",
  "description": "Session tokens not refreshing",
  "priority": "high",
  "project": "rubicon",
  "type": "bug"
}

Response 201: The created task object.

Get Task

GET /api/tasks/:id

Update Task

PATCH /api/tasks/:id

Body: Partial task fields to update (title, description, status, priority, assignee, etc.).

Headers:

If-Match: "task:task_20260531_abcd:3"

If the task has been updated since revision 3, the API returns 409 CONFLICT with the latest task in details.current.

Delete Task

DELETE /api/tasks/:id

Reorder Tasks

POST /api/tasks/reorder

Body: { "taskIds": ["TASK-003", "TASK-001", "TASK-002"] }

Bulk Update

POST /api/tasks/bulk-update

Body: { "taskIds": ["TASK-001", "TASK-002"], "updates": { "status": "done" } }

Bulk Archive

POST /api/tasks/bulk-archive-by-ids

Body: { "taskIds": ["TASK-001", "TASK-002"] }

Blocking Status

GET /api/tasks/:id/blocking-status

Returns whether a task is blocked by unresolved dependencies.

Dependencies

POST   /api/tasks/:id/dependencies          # Add dependency
DELETE /api/tasks/:id/dependencies/:targetId # Remove dependency
GET    /api/tasks/:id/dependencies           # List dependencies
GET    /api/tasks/:id/dependency-graph       # Full dependency graph

Progress & Checkpointing

GET  /api/tasks/:id/progress         # Get progress
PUT  /api/tasks/:id/progress         # Set progress
POST /api/tasks/:id/progress/append  # Append progress entry

POST   /api/tasks/:id/checkpoint     # Save checkpoint
GET    /api/tasks/:id/checkpoint     # Get checkpoint
DELETE /api/tasks/:id/checkpoint     # Clear checkpoint

Context

GET /api/tasks/:id/context

Returns enriched context for agent consumption (task + dependencies + observations).

Worktree (Git)

POST   /api/tasks/:id/worktree        # Create worktree branch
GET    /api/tasks/:id/worktree         # Get worktree status
DELETE /api/tasks/:id/worktree         # Remove worktree
POST   /api/tasks/:id/worktree/rebase  # Rebase worktree
POST   /api/tasks/:id/worktree/merge   # Merge worktree
GET    /api/tasks/:id/worktree/open    # Open in editor

Apply Template

POST /api/tasks/:id/apply-template

Demote Task

POST /api/tasks/:id/demote

Moves a task back to backlog.


Time Tracking

Mounted at /api/tasks.

Summary

GET /api/tasks/time/summary

Returns aggregate time tracking data across all tasks.

Start Timer

POST /api/tasks/:id/time/start

Stop Timer

POST /api/tasks/:id/time/stop

Add Manual Entry

POST /api/tasks/:id/time/entry

Body:

{
  "durationMs": 3600000,
  "description": "Code review"
}

Delete Entry

DELETE /api/tasks/:id/time/entry/:entryId

Observations

Observational memory for tasks — agents record learnings, blockers, and notes.

Add Observation

POST /api/tasks/:id/observations

Body:

{
  "content": "Rate limiter needs Redis for distributed deployments",
  "type": "insight",
  "agent": "codex-1"
}

List Observations

GET /api/tasks/:id/observations

Delete Observation

DELETE /api/tasks/:id/observations/:obsId

Search Observations (cross-task)

GET /api/observations?q=redis&type=insight

Analytics

GET /api/analytics/timeline   # Task completion timeline
GET /api/analytics/metrics    # Throughput, cycle time, WIP
GET /api/analytics/health     # Board health indicators

Configuration

Mounted at /api/config.

Get Config

GET /api/config

Repository Management

GET    /api/config/repos               # List repos
POST   /api/config/repos               # Add repo
PATCH  /api/config/repos/:name         # Update repo
DELETE /api/config/repos/:name         # Remove repo
POST   /api/config/repos/validate      # Validate repo config
GET    /api/config/repos/:name/branches # List branches

Agent Configuration

GET /api/config/agents        # List configured agents
PUT /api/config/agents        # Update agent config
PUT /api/config/default-agent # Set default agent

Settings

GET   /api/settings/features   # Get feature flags
PATCH /api/settings/features   # Toggle feature flags

Body (PATCH):

{
  "darkMode": true,
  "squadChat": true,
  "analyticsEnabled": true
}

Lifecycle Hooks

Event-driven hooks that fire on task state transitions.

GET    /api/hooks                # List hooks
GET    /api/hooks/executions     # List recent executions
POST   /api/hooks                # Create hook
PATCH  /api/hooks/:id            # Update hook
DELETE /api/hooks/:id            # Delete hook
POST   /api/hooks/fire           # Manually fire a hook

Create Hook Body:

{
  "name": "notify-on-done",
  "event": "task.status.changed",
  "filter": { "newStatus": "done" },
  "action": {
    "type": "webhook",
    "url": "https://example.com/webhook"
  }
}

Chat & Squad

Squad Chat

Post messages to the squad chat channel (agent coordination).

POST /api/chat/squad

Body:

{
  "agent": "VERITAS",
  "message": "Starting cleanup — 14 steps",
  "model": "claude-opus-4.6",
  "tags": ["cleanup"]
}
GET /api/chat/squad

Returns recent squad messages. Supports ?limit=N.

Chat Sessions

POST   /api/chat/send                 # Send message to a session
GET    /api/chat/sessions              # List sessions
GET    /api/chat/sessions/:id          # Get session
GET    /api/chat/sessions/:id/history  # Get session history
DELETE /api/chat/sessions/:id          # Delete session

Agent Status

Real-time agent activity indicator for the board.

GET  /api/agent/status   # Current status
POST /api/agent/status   # Update status

Update Body:

{
  "status": "working",
  "subAgentCount": 2,
  "activeAgents": [
    { "agent": "TARS", "status": "working", "taskTitle": "Fix auth" },
    { "agent": "CASE", "status": "working", "taskTitle": "Add tests" }
  ]
}

Delegation Violation

POST /api/agent/status/delegation-violation

Reports when an agent violates delegation rules.


Auth & Diagnostics

GET  /api/auth/status           # Check auth status & current role
POST /api/auth/setup            # Initial admin setup
POST /api/auth/login            # Login (returns JWT)
POST /api/auth/logout           # Logout / invalidate token
POST /api/auth/recover          # Account recovery
POST /api/auth/change-password  # Change password
POST /api/auth/rotate-secret    # Rotate JWT secret
GET  /api/auth/rotation-status  # JWT rotation status
POST /api/auth/device-pairing/exchange # Redeem a one-time pairing payload

Login Example

POST /api/auth/login

Body: { "password": "admin-password" }

Response 200:

{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "role": "admin",
  "expiresIn": "24h"
}

Identity & Workspaces

v5 adds SQLite-backed identity management for users, workspaces, memberships, roles, and invitations. These endpoints are mounted at /api/identity and /api/v1/identity.

MethodPathDescription
GET/api/identity/profileCurrent user profile plus workspace memberships.
GET/api/identity/workspacesWorkspaces available to the current user.
POST/api/identity/workspaces/switchValidate/select an active workspace membership.
GET/api/identity/workspaces/:workspaceId/membersList active workspace members.
GET/api/identity/workspaces/:workspaceId/invitationsList invitations. Requires admin.
POST/api/identity/workspaces/:workspaceId/invitationsCreate an invitation. Requires admin.
POST/api/identity/invitations/acceptAccept an invitation.
POST/api/auth/invitations/acceptAccept an invitation before login.
POST/api/identity/invitations/:id/revokeRevoke a pending invitation. Requires admin.
PATCH/api/identity/workspaces/:workspaceId/members/:idUpdate a member role. Requires admin.
DELETE/api/identity/workspaces/:workspaceId/members/:idRemove a member. Requires admin.
GET/api/identity/workspaces/:workspaceId/device-sessionsList trusted device sessions. Requires admin.
POST/api/identity/workspaces/:workspaceId/device-pairing-codesCreate a short-lived pairing payload. Requires admin.
POST/api/identity/workspaces/:workspaceId/device-sessions/:id/testTest current device session state. Requires admin.
POST/api/identity/workspaces/:workspaceId/device-sessions/:id/revokeRevoke a trusted device session. Requires admin.

Create Invitation

POST /api/identity/workspaces/local/invitations
{
  "email": "reviewer@example.com",
  "role": "reviewer"
}

The response includes the plaintext invitation token once. SQLite stores only the token hash.

Accept Invitation

POST /api/auth/invitations/accept
{
  "token": "plaintext-token-from-invite",
  "displayName": "Reviewer",
  "email": "reviewer@example.com"
}

Membership mutations are recorded in audit and activity history.

Device Pairing

POST /api/identity/workspaces/local/device-pairing-codes
{
  "deviceName": "Brad phone",
  "clientMode": "mobile-pwa",
  "capabilities": ["workspace:read", "task:read"],
  "scopes": ["workspace:read", "task:read"],
  "role": "read-only"
}

The response returns a plaintext code and veritas://pair?... link once. SQLite stores only hashes for pairing codes and device session secrets. Clients redeem the returned payload through:

POST /api/auth/device-pairing/exchange

Pairing payloads include client id, client mode, capabilities, device id, scopes, role, workspace, nonce, signed timestamp, and signature. Codes expire quickly, cannot be reused, and failed attempts are rate-limited and audited.


Telemetry

Run events, token usage, and metrics — powers the dashboard graphs.

Post Event

POST /api/telemetry/events

Body (run started):

{
  "type": "run.started",
  "taskId": "TASK-001",
  "agent": "veritas"
}

Body (run completed):

{
  "type": "run.completed",
  "taskId": "TASK-001",
  "agent": "veritas",
  "durationMs": 45000,
  "success": true
}

Body (token usage):

{
  "type": "run.tokens",
  "taskId": "TASK-001",
  "agent": "veritas",
  "model": "claude-opus-4.6",
  "inputTokens": 12000,
  "outputTokens": 3500,
  "cacheTokens": 8000,
  "cost": 0.15
}

Bulk Events

POST /api/telemetry/events/bulk

Body: { "events": [ ... ] }

Query Events

GET /api/telemetry/events                  # All events (?type=, ?limit=, ?taskId=)
GET /api/telemetry/events/task/:taskId     # Events for a specific task
GET /api/telemetry/status                  # Telemetry subsystem status
GET /api/telemetry/count                   # Event counts
GET /api/telemetry/export                  # Export events (CSV/JSON)

Health

Three-tier health check system for container orchestration.

EndpointAuthPurpose
GET /healthNoneAlias for /health/live
GET /health/liveNoneLiveness probe — process running
GET /health/readyNoneReadiness probe — storage, disk, memory
GET /health/deepAdminFull diagnostics — version, WS count, circuit breakers
GET /api/healthNoneLightweight API liveness signal
GET /api/health/deepAdminSame as /health/deep, under /api

Readiness Response:

{
  "status": "ok",
  "checks": { "storage": "ok", "memory": "ok", "disk": "ok" },
  "timestamp": "2026-03-02T07:00:00Z"
}

WebSocket

Endpoint: ws://localhost:3001/ws

Connection

const ws = new WebSocket('ws://localhost:3001/ws?api_key=YOUR_API_KEY');
  • Max connections: 50
  • Heartbeat: server pings every 30s; clients must pong within 10s
  • Origin validation enforced (CSWSH protection)

Authentication

Pass API key as api_key query parameter only for WebSocket clients that cannot send headers during the upgrade. HTTP requests must use Authorization: Bearer or X-API-Key. In production, do not rely on localhost bypass.

Client → Server Messages

Subscribe to task output:

{ "type": "subscribe", "taskId": "TASK-001" }

Subscribe to chat session:

{ "type": "chat:subscribe", "sessionId": "session-abc" }

Server → Client Messages

Task change broadcast:

{ "type": "task:updated", "task": { "id": "TASK-001", "status": "done" } }

Agent output:

{
  "type": "agent:output",
  "taskId": "TASK-001",
  "outputType": "stdout",
  "data": "Running tests..."
}

Chat message:

{ "type": "chat:message", "sessionId": "session-abc", "message": { ... } }

Agent status change:

{ "type": "agent:status", "status": "working", "activeAgents": [ ... ] }

Task Verification

Verification step checklists for tasks — define acceptance criteria that must be checked off before a task is considered truly complete.

Mounted at /api/tasks.

Add Verification Step

POST /api/tasks/:id/verification

Body:

{
  "description": "All unit tests passing"
}

Response 201: The updated task object with the new verification step added.

Update Verification Step

PATCH /api/tasks/:id/verification/:stepId

Body (partial):

{
  "checked": true
}

When checked changes, checkedAt is automatically set (or cleared).

Response 200: The updated task object.

Delete Verification Step

DELETE /api/tasks/:id/verification/:stepId

Response 200: The updated task object with the step removed.


Task Comments

Comment threads on tasks — supports adding, editing, and deleting comments. Comments auto-sync to linked GitHub issues.

Comment mutations use the parent task revision. Send the latest task ETag in If-Match when adding, editing, or deleting comments. A stale comment edit returns the same 409 CONFLICT shape documented in Tasks, with the latest task and comments in details.current.

Mounted at /api/tasks.

Add Comment

POST /api/tasks/:id/comments

Body:

{
  "author": "veritas",
  "text": "Root cause identified — auth middleware skips token refresh"
}

Response 201: The updated task object with the new comment.

Edit Comment

PATCH /api/tasks/:id/comments/:commentId

Body:

{
  "text": "Updated analysis — the issue is in the session store"
}

Delete Comment

DELETE /api/tasks/:id/comments/:commentId

Task Subtasks

Break tasks into smaller work items with optional acceptance criteria per subtask.

Mounted at /api/tasks.

Add Subtask

POST /api/tasks/:id/subtasks

Body:

{
  "title": "Add input validation",
  "acceptanceCriteria": ["Rejects empty strings", "Returns 400 on invalid input"]
}

Response 201: The updated task object.

Update Subtask

PATCH /api/tasks/:id/subtasks/:subtaskId

Body (partial):

{
  "completed": true
}

Delete Subtask

DELETE /api/tasks/:id/subtasks/:subtaskId

Toggle Acceptance Criterion

PATCH /api/tasks/:id/subtasks/:subtaskId/criteria

Body:

{
  "criteriaIndex": 0
}

Toggles the checked state of a specific acceptance criterion on a subtask.


Task Deliverables

Track deliverable artifacts (files, PRs, docs) produced by agents working on a task.

Mounted at /api/tasks.

List Deliverables

GET /api/tasks/:id/deliverables

Add Deliverable

POST /api/tasks/:id/deliverables

Body:

{
  "title": "API endpoint implementation",
  "type": "code",
  "path": "server/src/routes/new-feature.ts",
  "agent": "codex-1",
  "description": "REST endpoints for the new feature"
}

Response 201: The updated task object.

Update Deliverable

PATCH /api/tasks/:id/deliverables/:deliverableId

Body (partial): Any of title, type, path, status, description.

Delete Deliverable

DELETE /api/tasks/:id/deliverables/:deliverableId

Task Archive

Archive completed tasks (by sprint or individually) and restore them. Archived tasks are removed from the active board.

Mounted at /api/tasks.

MethodPathDescription
GET/api/tasks/archivedList all archived tasks
GET/api/tasks/archive/suggestionsGet sprints ready for archival
POST/api/tasks/archive/sprint/:sprintArchive all done tasks in a sprint
POST/api/tasks/bulk-archiveArchive by sprint name
POST/api/tasks/bulk-archive-by-idsArchive specific task IDs
POST/api/tasks/:id/archiveArchive a single task
POST/api/tasks/:id/restoreRestore a task from archive

Archive by Sprint

POST /api/tasks/archive/sprint/:sprint

Archives all completed tasks in the given sprint.

Response 200:

{
  "archived": 5
}

Archive Single Task

POST /api/tasks/:id/archive

Auth: Requires admin or agent role. Emits audit log entry.

Restore Task

POST /api/tasks/:id/restore

Restores an archived task back to active status (done).


Attachments

File upload/download for task attachments with automatic text extraction (PDF, DOCX, etc.).

Mounted at /api/tasks.

MethodPathDescription
POST/api/tasks/:id/attachmentsUpload files (multipart, max 20)
GET/api/tasks/:id/attachmentsList all attachments
GET/api/tasks/:id/attachments/:attIdGet attachment metadata
GET/api/tasks/:id/attachments/:attId/downloadDownload file
GET/api/tasks/:id/attachments/:attId/textGet extracted text
DELETE/api/tasks/:id/attachments/:attIdDelete attachment

Upload Attachments

POST /api/tasks/:id/attachments
Content-Type: multipart/form-data

Field: files — one or more files (max 20 per request).

Files undergo MIME validation via magic bytes. Text is automatically extracted from supported formats.

Response 200:

{
  "attachments": [
    {
      "id": "att_abc123",
      "filename": "design-spec.pdf",
      "originalName": "design-spec.pdf",
      "mimeType": "application/pdf",
      "size": 245000
    }
  ],
  "task": { "..." },
  "rejected": []
}

Get Extracted Text

GET /api/tasks/:id/attachments/:attId/text

Response 200:

{
  "attachmentId": "att_abc123",
  "text": "Extracted document content...",
  "hasText": true
}

Agent Permissions

Role-based permission levels for agents: intern, specialist, lead. Interns require approval for certain actions.

Mounted at /api/agents/permissions.

MethodPathDescription
GET/api/agents/permissionsList all agent permissions
GET/api/agents/permissions/:idGet agent permission config
PUT/api/agents/permissions/:id/levelSet permission level
PATCH/api/agents/permissions/:idUpdate permission fields
POST/api/agents/permissions/checkCheck if agent can perform action
POST/api/agents/permissions/approvalsRequest approval (intern)
GET/api/agents/permissions/approvalsList pending approvals
POST/api/agents/permissions/approvals/:idReview approval request

Set Permission Level

PUT /api/agents/permissions/:id/level

Body:

{
  "level": "specialist"
}

Valid levels: intern, specialist, lead.

Check Permission

POST /api/agents/permissions/check

Body:

{
  "agentId": "codex-1",
  "action": "deploy"
}

Response 200:

{
  "allowed": true,
  "level": "specialist",
  "requiresApproval": false
}

Update Permission Fields

PATCH /api/agents/permissions/:id

Body (partial):

{
  "trustedDomains": ["github.com"],
  "canCreateTasks": true,
  "canDelegate": false,
  "canApprove": false,
  "restrictions": ["no-deploy"]
}

Request Approval

POST /api/agents/permissions/approvals

Used by intern-level agents to request approval for restricted actions.

Review Approval

POST /api/agents/permissions/approvals/:id

Approve or reject a pending approval request.


Agent Routing

Automatic agent resolution — determines the best agent for a task based on configurable routing rules.

Mounted at /api/agents.

MethodPathDescription
POST/api/agents/routeResolve best agent for a task
GET/api/agents/routingGet routing configuration
PUT/api/agents/routingUpdate routing configuration

Resolve Agent

POST /api/agents/route

Accepts either a task ID or ad-hoc metadata:

By task ID:

{
  "taskId": "TASK-001"
}

By metadata:

{
  "type": "bug",
  "priority": "high",
  "project": "rubicon",
  "subtaskCount": 3
}

Response 200:

{
  "agent": "codex-1",
  "model": "claude-sonnet-4.5",
  "rule": "high-priority-bugs",
  "confidence": 0.95
}

Get/Update Routing Configuration

GET /api/agents/routing
PUT /api/agents/routing

PUT Body:

{
  "enabled": true,
  "rules": [
    {
      "id": "high-bugs",
      "name": "High priority bugs",
      "match": { "type": "bug", "priority": "high" },
      "agent": "codex-1",
      "model": "claude-sonnet-4.5",
      "enabled": true
    }
  ],
  "defaultAgent": "veritas",
  "fallbackOnFailure": true,
  "maxRetries": 2
}

Shared Resources

Registry for shared resources (credentials, config files, API keys, docs) that can be mounted to projects.

Mounted at /api/shared-resources.

MethodPathDescription
GET/api/shared-resourcesList all (filters: type, project, tag, name)
GET/api/shared-resources/:idGet one resource
POST/api/shared-resourcesCreate resource
PATCH/api/shared-resources/:idUpdate resource
DELETE/api/shared-resources/:idDelete resource
POST/api/shared-resources/:id/mountMount to project(s)
POST/api/shared-resources/:id/unmountUnmount from project(s)

Create Resource

POST /api/shared-resources

Body:

{
  "name": "Production DB Config",
  "type": "config",
  "content": "host=db.example.com\nport=5432",
  "tags": ["database", "production"],
  "projectIds": ["rubicon"]
}

Mount/Unmount

POST /api/shared-resources/:id/mount
POST /api/shared-resources/:id/unmount

Body:

{
  "projectIds": ["rubicon", "brainmeld"]
}

Doc Freshness

Track documentation freshness — monitor when docs were last reviewed and alert when they go stale.

Mounted at /api/doc-freshness.

MethodPathDescription
GET/api/doc-freshnessList tracked documents (filters: project, type, stale)
GET/api/doc-freshness/:idGet one tracked document
POST/api/doc-freshnessTrack a new document
PATCH/api/doc-freshness/:idUpdate document metadata
DELETE/api/doc-freshness/:idStop tracking
POST/api/doc-freshness/:id/reviewMark as freshly reviewed
GET/api/doc-freshness/alertsList freshness alerts (filters: severity, acknowledged)
POST/api/doc-freshness/alerts/:id/acknowledgeAcknowledge an alert
GET/api/doc-freshness/summaryFreshness health summary

Track a Document

POST /api/doc-freshness

Body:

{
  "path": "docs/API-REFERENCE.md",
  "type": "api-reference",
  "project": "veritas-kanban",
  "maxAgeDays": 30
}

Mark as Reviewed

POST /api/doc-freshness/:id/review

Body (optional):

{
  "reviewer": "brad",
  "reviewedAt": "2026-03-08T10:00:00Z"
}

Get Freshness Summary

GET /api/doc-freshness/summary

Response 200:

{
  "total": 15,
  "fresh": 12,
  "stale": 2,
  "critical": 1,
  "alertCount": 3
}

Cost Prediction

Predict token costs for tasks before execution — uses historical telemetry data to estimate.

Mounted at /api/cost-prediction.

MethodPathDescription
POST/api/cost-prediction/predictPredict cost for a task
GET/api/cost-prediction/accuracyPrediction accuracy for completed tasks
GET/api/cost-prediction/accuracy/statsAggregate accuracy statistics

Predict Cost

POST /api/cost-prediction/predict

By task ID:

{
  "taskId": "TASK-001"
}

By metadata:

{
  "type": "feature",
  "priority": "high",
  "project": "rubicon",
  "description": "Implement OAuth2 flow",
  "subtaskCount": 5
}

Response 200:

{
  "estimatedTokens": 45000,
  "estimatedCost": 0.85,
  "estimatedDurationMs": 120000,
  "confidence": 0.78,
  "basedOn": 12
}

Get Accuracy Stats

GET /api/cost-prediction/accuracy/stats

Returns aggregate statistics on prediction accuracy across all completed tasks.


Error Learning

Structured failure analysis — submit errors, record root causes, and search for similar past errors to avoid repeating mistakes.

Mounted at /api/errors.

MethodPathDescription
POST/api/errors/submitSubmit an error for analysis
GET/api/errorsList analyses (filters: taskId, errorType, severity, agent, limit)
GET/api/errors/:idGet specific analysis
PATCH/api/errors/:idUpdate with root cause & fix
GET/api/errors/statsAggregate error pattern stats
GET/api/errors/searchSearch similar past errors (?q=<query>)

Submit Error

POST /api/errors/submit

Body:

{
  "taskId": "TASK-001",
  "agent": "codex-1",
  "errorMessage": "ECONNREFUSED 127.0.0.1:5432",
  "errorType": "resource",
  "rawDetails": "Full stack trace...",
  "attemptDescription": "Trying to connect to PostgreSQL"
}

Valid error types: runtime, api, validation, timeout, permission, resource, model, git, build, test, configuration, unknown.

Response 201: The created error analysis object.

Update Analysis

PATCH /api/errors/:id

Body (partial):

{
  "rootCause": "PostgreSQL service not running",
  "severity": "medium",
  "chosenFix": "Add health check before DB operations",
  "preventionSteps": ["Add connection retry logic", "Check service status on startup"],
  "tags": ["database", "connectivity"]
}

Search Similar Errors

GET /api/errors/search?q=ECONNREFUSED&limit=5

Returns past errors similar to the query string — useful for avoiding repeated mistakes.


QMD-ready retrieval across task markdown and docs. The endpoint uses the configured backend and gracefully falls back to keyword search when QMD is unavailable.

Mounted at /api/search.

MethodPathDescription
POST/api/searchSearch task and docs collections with one query
POST/api/search/index/refreshRefresh QMD collections and embeddings

Search Collections

POST /api/search

Body:

{
  "query": "semantic search duplicate detection",
  "limit": 10,
  "collections": ["tasks-active", "tasks-archive", "docs"],
  "backend": "auto"
}

backend may be keyword, qmd, or auto. QMD is opt-in via VERITAS_SEARCH_BACKEND=qmd or per-request backend: "qmd".

Response 200:

{
  "query": "semantic search duplicate detection",
  "backend": "keyword",
  "degraded": false,
  "elapsedMs": 12,
  "results": [
    {
      "id": "tasks/active/task_20260504_example.md",
      "title": "Add semantic search",
      "path": "tasks/active/task_20260504_example.md",
      "collection": "tasks-active",
      "snippet": "Wire QMD retrieval into Veritas.",
      "score": 4
    }
  ]
}

QMD Setup

npm install -g @tobilu/qmd
pnpm qmd:setup
VERITAS_SEARCH_BACKEND=qmd pnpm dev

QMD Index Refresh

POST /api/search/index/refresh

Body:

{
  "embed": true
}

Set embed to false to run only qmd update.

Response 200:

{
  "backend": "qmd",
  "updated": true,
  "embedded": true,
  "elapsedMs": 982,
  "commands": ["update", "embed"]
}

Tool Policies

Role-based tool access restrictions — control which tools each agent role can use.

Mounted at /api/tool-policies.

MethodPathDescription
GET/api/tool-policiesList all policies
GET/api/tool-policies/:roleGet policy for a role
POST/api/tool-policiesCreate a new policy
PUT/api/tool-policies/:roleUpdate an existing policy
DELETE/api/tool-policies/:roleDelete a custom policy
POST/api/tool-policies/:role/validateCheck if a tool is allowed for a role

Create Policy

POST /api/tool-policies

Body:

{
  "role": "intern",
  "allowed": ["read", "search", "analyze"],
  "denied": ["deploy", "delete", "admin"],
  "description": "Restricted access for intern agents"
}

Validate Tool Access

POST /api/tool-policies/:role/validate

Body:

{
  "tool": "deploy"
}

Response 200:

{
  "role": "intern",
  "tool": "deploy",
  "allowed": false
}

Traces

Distributed execution tracing — record and query traces for agent task attempts.

Mounted at /api/traces.

MethodPathDescription
GET/api/traces/statusCheck if tracing is enabled
POST/api/traces/enableEnable tracing
POST/api/traces/disableDisable tracing
GET/api/traces/:attemptIdGet a trace by attempt ID
GET/api/traces/task/:taskIdList all traces for a task

Check Tracing Status

GET /api/traces/status

Response 200:

{
  "enabled": true
}

Get Task Traces

GET /api/traces/task/TASK-001

Returns all execution traces associated with the given task.


Audit

Immutable, hash-chained audit log. Admin only.

Mounted at /api/audit.

MethodPathDescription
GET/api/auditRecent audit entries (?limit=N, default 100, max 1000)
GET/api/audit/verifyVerify hash chain integrity of current month's log

Auth: Requires admin role.

Query Audit Log

GET /api/audit?limit=50

Response 200:

{
  "entries": [
    {
      "timestamp": "2026-03-08T07:00:00Z",
      "action": "task.archive",
      "actor": "admin-key",
      "resource": "TASK-001",
      "details": { "title": "Fix auth bug" },
      "hash": "sha256:..."
    }
  ],
  "count": 50
}

Verify Integrity

GET /api/audit/verify

Verifies the hash chain of the current month's audit log file. Returns chain validity and any broken links.


Common Workflows

Agent Task Lifecycle

# 1. Create task
TASK=$(curl -s -X POST http://localhost:3001/api/tasks \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: YOUR_KEY' \
  -d '{"title":"Fix bug","priority":"high"}' | jq -r '.id')

# 2. Start time tracking
curl -s -X POST http://localhost:3001/api/tasks/$TASK/time/start

# 3. Emit telemetry
curl -s -X POST http://localhost:3001/api/telemetry/events \
  -H 'Content-Type: application/json' \
  -d "{\"type\":\"run.started\",\"taskId\":\"$TASK\",\"agent\":\"veritas\"}"

# 4. Update status to in-progress
curl -s -X PATCH http://localhost:3001/api/tasks/$TASK \
  -H 'Content-Type: application/json' \
  -d '{"status":"in-progress"}'

# 5. Save checkpoint mid-work
curl -s -X POST http://localhost:3001/api/tasks/$TASK/checkpoint \
  -H 'Content-Type: application/json' \
  -d '{"state":{"step":3,"context":"halfway done"}}'

# 6. Add observation
curl -s -X POST http://localhost:3001/api/tasks/$TASK/observations \
  -H 'Content-Type: application/json' \
  -d '{"content":"Found root cause in auth middleware","type":"insight","agent":"veritas"}'

# 7. Complete
curl -s -X PATCH http://localhost:3001/api/tasks/$TASK \
  -H 'Content-Type: application/json' \
  -d '{"status":"done"}'

# 8. Stop timer + emit completion telemetry
curl -s -X POST http://localhost:3001/api/tasks/$TASK/time/stop
curl -s -X POST http://localhost:3001/api/telemetry/events \
  -H 'Content-Type: application/json' \
  -d "{\"type\":\"run.completed\",\"taskId\":\"$TASK\",\"agent\":\"veritas\",\"durationMs\":45000,\"success\":true}"

Agent Loop (Poll for Work)

# Get next available task
NEXT=$(curl -s http://localhost:3001/api/tasks?status=todo&limit=1 | jq -r '.tasks[0].id')
if [ "$NEXT" != "null" ]; then
  # Claim it
  curl -s -X PATCH http://localhost:3001/api/tasks/$NEXT \
    -H 'Content-Type: application/json' \
    -d '{"status":"in-progress","assignee":"agent-1"}'
fi

Blocker Tracking

# Add a blocker observation
curl -s -X POST http://localhost:3001/api/tasks/TASK-001/observations \
  -H 'Content-Type: application/json' \
  -d '{"content":"Blocked: waiting on API key from vendor","type":"blocker","agent":"veritas"}'

# Add a dependency
curl -s -X POST http://localhost:3001/api/tasks/TASK-001/dependencies \
  -H 'Content-Type: application/json' \
  -d '{"targetId":"TASK-002","type":"blocked-by"}'

Webhook Hook Setup

# Fire a webhook when any task moves to "done"
curl -s -X POST http://localhost:3001/api/hooks \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "done-notify",
    "event": "task.status.changed",
    "filter": {"newStatus":"done"},
    "action": {"type":"webhook","url":"https://example.com/hook"}
  }'

Versioning & Deprecation

  • Current version: v1 (mounted at /api/v1, aliased at /api)
  • No breaking changes within a major version
  • Deprecations will be announced via:
    • Deprecation response header
    • Changelog entry
    • Minimum 2 minor releases before removal
  • When v2 ships, v1 will remain available for at least 6 months

Rate Limits

TierLimitApplies To
Global300 req/minAll endpoints (localhost exempt)
Read300 req/minGET endpoints
Write60 req/minPOST/PUT/PATCH/DELETE
Upload20 req/minFile upload endpoints

Rate limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.


Additional Endpoint Groups

These endpoints follow the same auth/error patterns documented above:

MountPurpose
/api/projectsProject CRUD
/api/sprintsSprint management
/api/backlogBacklog operations
/api/agentsAgent CRUD, routing
/api/agents/registerAgent self-registration
/api/agents/permissionsAgent permission management
/api/templatesTask templates
/api/task-typesCustom task type definitions
/api/activityActivity feed
/api/notificationsUser notifications
/api/broadcastsBroadcast messages
/api/changesEfficient agent polling (change feed)
/api/diffTask diff comparisons
/api/automationAutomation rules
/api/summaryBoard summaries
/api/githubGitHub integration
/api/conflictsMerge conflict detection
/api/metricsPrometheus-style metrics
/api/tracesDistributed tracing
/api/cost-predictionToken cost forecasting
/api/error-learningError pattern learning
/api/reportsGenerated reports
/api/deliverablesScheduled deliverables
/api/doc-freshnessDocumentation freshness tracking
/api/docsDocs endpoint
/api/shared-resourcesShared resource management
/api/status-historyTask status history
/api/digestDigest generation
/api/auditAudit log
/api/lessonsLessons learned
/api/delegationTask delegation
/api/workflowsWorkflow engine (details)
/api/tool-policiesTool access policies
/api/integrationsExternal integrations
/api/settings/transition-hooksStatus transition hooks

| /api/feedback | User feedback & sentiment analytics | | /api/decisions | Decision audit trail | | /api/drift | Behavioral drift detection | | /api/policies | Agent policy & guard engine | | /api/scoring/profiles | Output evaluation profiles | | /api/scoring/evaluate | Run an output evaluation | | /api/scoring/history | Evaluation history | | /api/prompt-registry | Prompt template registry | | /api/v1/system/health | Global system health |


v4.0 API Reference

User Feedback (/api/feedback)

Collect feedback on agent outputs and query aggregate sentiment analytics.

List Feedback

GET /api/feedback

Query params: agent, taskId, sentiment (positive | neutral | negative), since (ISO timestamp), limit (default 50), offset.

Response: Array of feedback objects.

[
  {
    "id": "fb_abc123",
    "content": "The summary was concise and accurate.",
    "sentiment": "positive",
    "category": "output-quality",
    "agent": "TARS",
    "taskId": "task_20260321_abc",
    "createdAt": "2026-03-21T14:00:00.000Z"
  }
]

Submit Feedback

POST /api/feedback
{
  "content": "The response missed the key point.",
  "sentiment": "negative",
  "category": "accuracy",
  "agent": "CASE",
  "taskId": "task_20260321_xyz"
}

Response: 201 with created feedback object.

Get Feedback Item

GET /api/feedback/:id

Response: Single feedback object.

Delete Feedback

DELETE /api/feedback/:id

Response: 204 No Content.

Feedback Analytics

GET /api/feedback/analytics

Query params: agent, since, until.

Response:

{
  "total": 42,
  "sentimentBreakdown": {
    "positive": 30,
    "neutral": 8,
    "negative": 4
  },
  "topCategories": [
    { "category": "output-quality", "count": 18 },
    { "category": "accuracy", "count": 12 }
  ],
  "trend": [{ "date": "2026-03-21", "positive": 5, "neutral": 1, "negative": 0 }]
}

Decision Audit Trail (/api/decisions)

Log agent decisions with assumptions and record outcomes.

List Decisions

GET /api/decisions

Query params: agent, taskId, minConfidence (0–1), maxConfidence (0–1), since, until, limit, offset.

Response: Array of decision objects.

[
  {
    "id": "dec_abc123",
    "decision": "Use Redis for session caching",
    "confidence": 0.85,
    "reasoning": "Redis has sub-ms latency and supports TTL natively.",
    "evidence": ["benchmark results", "existing infra"],
    "assumptions": ["Redis cluster is available", "TTL of 1h is sufficient"],
    "agent": "VERITAS",
    "taskId": "task_20260321_abc",
    "createdAt": "2026-03-21T14:00:00.000Z",
    "outcome": null
  }
]

Log a Decision

POST /api/decisions
{
  "decision": "Refactor auth to use JWT instead of sessions",
  "confidence": 0.9,
  "reasoning": "Sessions require sticky routing; JWT is stateless.",
  "evidence": ["architecture review notes"],
  "assumptions": ["Clients will store tokens securely"],
  "agent": "VERITAS",
  "taskId": "task_20260321_abc"
}

Response: 201 with created decision object.

Get Decision

GET /api/decisions/:id

Update an Assumption

PATCH /api/decisions/:id/assumptions/:idx

Update a specific assumption by its zero-based index.

{
  "text": "Clients will store tokens securely (confirmed via security review)",
  "held": true
}

Response: Updated decision object with the assumption patched.


Behavioral Drift Detection (/api/drift)

Track agent metric baselines and detect behavioral deviations.

List Drift Alerts

GET /api/drift/alerts

Query params: agent, acknowledged (boolean), since, limit.

Response: Array of drift alert objects.

[
  {
    "id": "drift_abc123",
    "agent": "TARS",
    "metric": "task_completion_rate",
    "baseline": 0.92,
    "current": 0.71,
    "deviation": 0.21,
    "threshold": 0.1,
    "severity": "high",
    "acknowledged": false,
    "detectedAt": "2026-03-21T14:00:00.000Z"
  }
]

Acknowledge Drift Alert

POST /api/drift/alerts/:id/acknowledge
{
  "notes": "Agent was rate-limited by upstream API — not a behavior change."
}

Response: Updated alert with acknowledged: true.

List Baselines

GET /api/drift/baselines

Query params: agent, metric.

Response: Array of baseline records showing current metric norms per agent.

Reset Baselines

POST /api/drift/baselines/reset
{
  "agent": "TARS",
  "metric": "task_completion_rate"
}

Response: 200 with updated baseline record.

Run Drift Analysis

POST /api/drift/analyze
{
  "agent": "TARS"
}

Compares current metrics against baselines and creates alerts for any out-of-threshold deviations.

Response: 200 with analysis summary including number of alerts created.


Agent Policy Engine (/api/policies)

Define configurable guard rules for agent tool and action access.

List Policies

GET /api/policies

Query params: agent, project, enabled (boolean).

Response: Array of policy objects.

[
  {
    "id": "pol_abc123",
    "name": "No web access for Intern agents",
    "description": "Intern-level agents cannot use browser or fetch tools.",
    "enabled": true,
    "scope": { "agentLevel": "intern" },
    "rules": [
      {
        "tool": "browser",
        "action": "*",
        "effect": "deny"
      }
    ],
    "precedence": "deny-first",
    "createdAt": "2026-03-21T14:00:00.000Z"
  }
]

Create Policy

POST /api/policies
{
  "name": "Require approval for file deletion",
  "enabled": true,
  "scope": { "global": true },
  "rules": [
    {
      "tool": "exec",
      "action": "rm",
      "effect": "require-approval"
    }
  ],
  "precedence": "deny-first"
}

Response: 201 with created policy object.

Get Policy

GET /api/policies/:id

Update Policy

PUT /api/policies/:id

Delete Policy

DELETE /api/policies/:id

Response: 204 No Content.

Evaluate Policy

POST /api/policies/:id/evaluate
{
  "agent": "TARS",
  "tool": "browser",
  "action": "navigate",
  "metadata": { "url": "https://example.com" }
}

Response:

{
  "allowed": false,
  "effect": "deny",
  "matchedRule": { "tool": "browser", "action": "*", "effect": "deny" },
  "policyId": "pol_abc123",
  "auditId": "audit_xyz789"
}

Output Evaluation & Scoring (/api/scoring)

Create scoring profiles and evaluate agent outputs against weighted criteria.

List Scoring Profiles

GET /api/scoring/profiles

Query params: limit, offset.

Response: Array of scoring profile objects.

Create Scoring Profile

POST /api/scoring/profiles
{
  "name": "Code Quality Baseline",
  "description": "Checks for common quality indicators in generated code.",
  "compositeMethod": "weightedAvg",
  "scorers": [
    {
      "id": "s1",
      "name": "No hardcoded secrets",
      "type": "RegexMatch",
      "pattern": "(password|secret|api_key)\\s*=\\s*['\"][^'\"]+['\"]",
      "flags": "i",
      "invert": true,
      "weight": 2,
      "scoreOnMatch": 0,
      "scoreOnMiss": 1
    },
    {
      "id": "s2",
      "name": "Has error handling",
      "type": "KeywordContains",
      "keywords": ["try", "catch", "error"],
      "matchMode": "any",
      "weight": 1
    }
  ]
}

Response: 201 with created profile.

Get Scoring Profile

GET /api/scoring/profiles/:id

Update Scoring Profile

PUT /api/scoring/profiles/:id

Delete Scoring Profile

DELETE /api/scoring/profiles/:id

Response: 204 No Content.

Evaluate Output

POST /api/scoring/evaluate
{
  "profileId": "prof_abc123",
  "output": "function getUser(id) {\n  try {\n    return db.find(id);\n  } catch (e) {\n    throw e;\n  }\n}",
  "action": "generate_function",
  "agent": "TARS",
  "taskId": "task_20260321_abc"
}

Response:

{
  "id": "eval_xyz789",
  "profileId": "prof_abc123",
  "score": 0.88,
  "compositeMethod": "weightedAvg",
  "scorerResults": [
    { "id": "s1", "name": "No hardcoded secrets", "score": 1.0, "weight": 2 },
    { "id": "s2", "name": "Has error handling", "score": 1.0, "weight": 1 }
  ],
  "agent": "TARS",
  "taskId": "task_20260321_abc",
  "evaluatedAt": "2026-03-21T14:00:00.000Z"
}

Evaluation History

GET /api/scoring/history

Query params: profileId, agent, taskId, since, limit, offset.

Response: Array of past evaluation results.


Prompt Template Registry (/api/prompt-registry)

Manage version-controlled prompt templates with variable extraction and usage tracking.

List Templates

GET /api/prompt-registry

Query params: tag, search, limit, offset.

Response: Array of template summaries (without full content for performance).

Create Template

POST /api/prompt-registry
{
  "name": "Task Completion Summary",
  "description": "Generates a completion summary for a finished task.",
  "content": "You completed task {{task_title}}. Summarize what was done in 2-3 sentences, referencing the acceptance criteria: {{acceptance_criteria}}",
  "tags": ["completion", "summary"],
  "changelog": "Initial version"
}

Response: 201 with created template including auto-extracted variables (task_title, acceptance_criteria).

Get Template

GET /api/prompt-registry/:id

Response: Full template with current content, version number, variables list, and metadata.

Update Template

PATCH /api/prompt-registry/:id

Body: Partial template fields. Triggers automatic version creation.

{
  "content": "You completed task {{task_title}} (ID: {{task_id}}). Summarize...",
  "changelog": "Added task_id variable"
}

Delete Template

DELETE /api/prompt-registry/:id

Response: 204 No Content.

List Versions

GET /api/prompt-registry/:id/versions

Response: Array of version objects (id, versionNumber, changelog, createdAt). Does not include full content for performance.

Get Usage History

GET /api/prompt-registry/:id/usage

Query params: limit, offset.

Response: Array of usage records with model, token counts, and timestamps.

Template Stats

GET /api/prompt-registry/:id/stats

Response:

{
  "totalUses": 42,
  "averageInputTokens": 312,
  "averageOutputTokens": 128,
  "lastUsedAt": "2026-03-21T14:00:00.000Z"
}

Aggregate Stats (All Templates)

GET /api/prompt-registry/stats/all

Response: Aggregate usage stats across all templates.

Preview Template

POST /api/prompt-registry/:id/render-preview
{
  "variables": {
    "task_title": "Add OAuth login",
    "acceptance_criteria": "Users can log in with Google."
  }
}

Response: { "rendered": "You completed task Add OAuth login. Summarize..." }

Record Usage

POST /api/prompt-registry/:id/record-usage
{
  "model": "anthropic/claude-sonnet-4-6",
  "inputTokens": 320,
  "outputTokens": 145,
  "renderedOutput": "You completed task Add OAuth login...",
  "variables": { "task_title": "Add OAuth login" }
}

Response: 201 with logged usage record.


SQLite Portability (/api/v1/sqlite)

Admin-only endpoints for v5 file-to-SQLite migration and backup portability.

Dry-Run File Migration

POST /api/v1/sqlite/migration/dry-run
{
  "sourceRoot": "/path/to/project",
  "sqlitePath": "/path/to/.veritas-kanban/veritas.db",
  "journalPath": "/path/to/.veritas-kanban/sqlite-migration-journal.json"
}

Returns entity counts and warnings without creating or mutating the database.

Run File Migration

POST /api/v1/sqlite/migration/run
{
  "sourceRoot": "/path/to/project",
  "sqlitePath": "/path/to/.veritas-kanban/veritas.db",
  "backupDir": "/path/to/pre-migration-backup",
  "journalPath": "/path/to/.veritas-kanban/sqlite-migration-journal.json"
}

Creates a timestamped source backup, imports supported file-backed data into SQLite, and returns a migration report.

Migration Recovery State

GET /api/v1/sqlite/migration/recovery?sourceRoot=/path/to/project&sqlitePath=/path/to/.veritas-kanban/veritas.db

Returns the latest migration journal, safe-mode recommendation, backup restore availability, source-file availability, SQLite readability, next actions, and artifacts to preserve for support.

Restore Pre-Migration Backup

POST /api/v1/sqlite/migration/restore-backup
{
  "backupPath": "/path/to/pre-migration-backup",
  "targetRoot": "/path/to/project",
  "journalPath": "/path/to/.veritas-kanban/sqlite-migration-journal.json",
  "replaceExisting": true,
  "dryRun": false
}

Restores the file-backed tasks/ and .veritas-kanban/ content from the pre-migration backup. Non-empty targets require replaceExisting: true; use dryRun: true to verify the paths and file count before overwriting.

Export Backup Bundle

POST /api/v1/sqlite/export
{
  "sqlitePath": "/path/to/.veritas-kanban/veritas.db",
  "outputDir": "/path/to/backup-bundle"
}

Writes raw SQLite table snapshots plus human-readable Markdown/JSON/YAML files.

Import Backup Bundle

POST /api/v1/sqlite/import
{
  "sqlitePath": "/path/to/fresh.db",
  "bundleDir": "/path/to/backup-bundle",
  "replaceExisting": true
}

Restores the bundle into SQLite and rebuilds derived search indexes.


System Health (/api/v1/system/health)

Get a real-time snapshot of system health across resources, agents, and operations.

GET /api/v1/system/health

No query params required.

Response:

{
  "status": "stable",
  "level": 0,
  "signals": {
    "system": {
      "status": "stable",
      "storageUsedPercent": 42,
      "diskFreeGb": 120,
      "memoryUsedPercent": 58
    },
    "agents": {
      "status": "stable",
      "online": 3,
      "offline": 0,
      "total": 3
    },
    "operations": {
      "status": "stable",
      "successRate": 0.97,
      "recentRuns": 50,
      "recentFailures": 1
    }
  },
  "timestamp": "2026-03-21T14:00:00.000Z"
}

Health levels: stable (0) · reviewing (1) · drifting (2) · elevated (3) · alert (4)


For workflow engine endpoints, see API-WORKFLOWS.md.
For MCP server tools, see MCP Server Guide.
For agent workflow SOPs, see SOP-agent-task-workflow.md.