Slop ยท API Reference
API Contracts
Two mutation surfaces: Next.js Server Actions (imported by React components) and REST API routes (consumed by client fetch and external skills).
Server Actions
REST API
ActionResult union
SSE stream
Mutations
Server Actions - by domain
All actions live in src/app/actions/, split into one file per domain. Each delegates to the daemon via getRunningDaemon() after validating its inputs. The table columns note what is validated, which daemon method is called, and which path is revalidated on success.
Batch
4 actions
Manages issue batches: creation, membership, and archival. All scoped to a repoId.
| Action | Validates | Daemon op | Revalidates |
createBatch | repoId, name non-empty | — | / |
addIssueToBatch | batchId, source, issueNumber, repoId | — | / |
removeIssueFromBatch | batchId, source, issueNumber | — | / |
archiveBatch | batchId non-empty | — | / |
Config
8 actions
Global settings mutations. saveConfig validates implementMode enum, acceptedReviewLevel enum, all timeout fields as positive integers, and boolean flags.
| Action | Validates | Daemon op | Revalidates |
saveConfig | implementMode, acceptedReviewLevel, timeout ints, booleans | — | /config |
setConfigMode | key in allowed set, value enum | — | /config |
saveRepoConcurrency | repoId, cap null or positive int | — | /config |
setPollPaused | paused boolean | — | /config |
setPointsHarness | harness AgentHarness enum | — | /config |
saveGitHubToken | token non-empty string | — | /config |
wipeDatabase | confirmation text | wipeDatabase() | / |
enableGuards | — | enableGuards() | /config |
Internal Issues
9 actions
CRUD operations for the internal issue tracker, plus label management and skill invocation on individual issues.
| Action | Validates | Daemon op | Revalidates |
startIssueSkill | repoId, issueNumber, mode ∈ {refine, review} | — | — |
createInternalIssue | repoId, title non-empty | — | /[repoId]/issues |
importBmadStories | repoId, files array non-empty | — | /[repoId]/issues |
updateInternalIssue | id, input fields | — | /[repoId]/issues |
setInternalIssueState | id, state InternalIssueState enum | — | /[repoId]/issues |
createLabelAction | repoId, name, color (#rrggbb) | — | /[repoId]/labels |
updateLabelAction | id, input fields | — | /[repoId]/labels |
deleteLabelAction | id non-empty | — | /[repoId]/labels |
addInternalIssueComment | id, body non-empty | — | /[repoId]/issues/[id] |
Issues
7 actions
Controls issue lifecycle on the Kanban board: readiness, ordering, config overrides, and triggering implementation.
| Action | Validates | Daemon op | Revalidates |
setIssueConfig | repoId, issueNumber, overrides shape | — | / |
suggestIssuePoints | repoId, issueNumber | — | — |
startIssue | repoId + issueNumber from FormData | startIssue() | / |
setIssueReady | repoId, issueNumber, ready boolean | setIssueReady() | / |
returnIssueToBacklog | repoId, issueNumber | returnIssueToBacklog() | / |
reorderReadyIssue | repoId, issueNumber, toIndex ≥ 0 | reorderReadyIssue() | / |
closeIssue | repoId + issueNumber from FormData | — | / |
PRs
6 actions
PR lifecycle actions: merging, syncing branches, closing, reviewing, and addressing review comments.
| Action | Validates | Daemon op | Revalidates |
mergePr | repoId + prNumber from FormData | mergePr() | / |
syncBranch | repoId from FormData | syncBranch() | / |
fixBaseCi | repoId from FormData | fixBaseCi() | / |
closePr | repoId + prNumber from FormData | closePr() | / |
reviewPr | repoId + prNumber from FormData | reviewPr() | / |
addressPr | repoId + prNumber from FormData | addressPr() | / |
Repos
2 actions
addRepo validates that the slug matches owner/name format, the path is absolute, and <path>/.git exists on disk. removeRepo cascades worker/worktree cleanup through the daemon.
| Action | Validates | Daemon op | Revalidates |
addRepo | owner/name slug, absolute path, .git exists | addRepo() | /config |
removeRepo | repoId non-empty | removeRepo() | /config |
Runs
5 actions
Manages skill runs and worker report issues. saveDoc dispatches a haiku+low-effort skill run to write a document file.
| Action | Validates | Daemon op | Revalidates |
createWorkerReportIssue | workerId non-empty | — | / |
cancelWorkerReportIssue | runId non-empty | — | / |
runSkillRun | skillName in allowed set, args shape | — | / |
saveDoc | filename allowlisted, content non-empty | — | /docs |
cancelSkillRun | runId non-empty | — | / |
Workers
9 actions
Full worker lifecycle control. Most accept a workerId from FormData and delegate directly to the daemon. clearFinishedWorkers is a bulk sweep with no daemon call.
| Action | Validates | Daemon op | Revalidates |
startWorker | repoId + issueNumber from FormData | startWorker() | / |
pauseWorker | workerId from FormData | pauseWorker() | / |
restartWorker | workerId from FormData | restartWorker() | / |
cancelWorker | workerId from FormData | cancelWorker() | / |
retryWorker | workerId from FormData | — | / |
setWorkerOverrides | workerId, overrides shape | — | / |
overrideToMerged | workerId from FormData | overrideToMerged() | / |
mergeWorker | workerId from FormData | mergeWorker() | / |
clearFinishedWorkers | — | — | / |
HTTP
REST API Routes
All routes live under src/app/api/. Every route file exports export const dynamic = "force-dynamic". Authentication is enforced at the Next.js middleware layer - unauthenticated requests receive 401 before reaching the route handler.
Events
SSE
| Method + Path | Query / Body | Response | Notes |
| GET/api/events |
— |
text/event-stream |
Server-Sent Events stream. Heartbeat comment every 25 s to keep the connection alive through proxies. Used by the board UI for live worker status updates. |
Workers
2 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/workers |
?repo=owner/name |
Worker array |
Includes computed costUsd and netTokens fields derived from session stats. |
| GET/api/workers/[id]/events |
?all flag |
Event array |
Without ?all, returns only recent events. With ?all, returns full event history for the worker. |
Runs
2 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/runs/[id] |
— |
{ status, lastError } |
Lightweight status poll for a skill run or worker report run. |
| GET/api/runs/[id]/events |
— |
Event array (≤ 100) |
Event log for a run, capped at 100 entries. |
Internal Issues
5 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/internal-issues |
?repo=owner/name |
Issue array |
Returns all internal issues for the repo, ordered by creation. |
| POST/api/internal-issues |
{ repoId, title, body?, labels? } |
Created issue, 201 |
Creates a new internal issue. Labels is an array of label IDs. |
| GET/api/internal-issues/[id] |
— |
Issue object |
Single issue with full body and metadata. |
| PATCH/api/internal-issues/[id] |
Partial issue fields |
Updated issue |
Partial update - only provided fields are changed. |
| GET/api/internal-issues/[id]/comments |
— |
Comment array |
All comments on a single internal issue, ordered chronologically. |
Labels
4 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/labels |
?repoId=owner/name |
Label array |
Uses repoId param, not repo. |
| POST/api/labels |
{ repoId, name, color, description? } |
Created label, 201 |
Color must be a valid hex string like #6c63ff. |
| PATCH/api/labels/[id] |
Partial label fields |
Updated label |
Partial update of name, color, or description. |
| DELETE/api/labels/[id] |
— |
204 No Content |
Hard deletes the label and removes it from all associated issues. |
Query param naming inconsistency: Most routes use ?repo=<owner/name> but /api/labels uses ?repoId=<owner/name>. This is a known inconsistency - use the correct param for each route.
Documents
2 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/docs |
?repo=owner/name |
Filename array |
Lists available document filenames from the repo's docs directory. |
| GET/api/docs/[filename] |
— |
text/plain |
Serves the raw document content. Restricted to an ALLOWED_DOC_FILES allowlist - path traversal is structurally impossible since the filename segment cannot contain slashes. |
Features
2 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/features |
?repo=owner/name |
.html filename array |
Lists available feature documentation HTML filenames. |
| GET/api/features/[filename] |
— |
text/html |
Serves a feature doc HTML file for sandboxed iframe rendering in the UI. Filenames are validated against the allowed set. |
Other routes
5 endpoints
| Method + Path | Query / Body | Response | Notes |
| GET/api/health |
— |
{ ready: boolean } |
Daemon readiness check used by the UI to show the guard screen. |
| GET/api/repo |
?repo=owner/name |
Annotated repo state or null |
Returns the cached repo snapshot state with PR and CI annotations. |
| POST/api/repo |
?repo=owner/name |
Updated repo state |
Forces a live GitHub refresh, bypassing the cache. Used by the repo view's manual refresh button. |
| GET/api/agents |
?repo=owner/name |
Agent row array |
Returns agent harness rows for the configured repo. |
| GET/api/bmad-stories |
?repo=owner/name |
Story row array with imported flag |
Returns BMAD story records, each annotated with whether it has been imported as an internal issue. |
Core
Daemon Interface
The Daemon interface is defined in src/server/daemon/types.ts and implemented in src/server/daemon/index.ts. All Server Actions that need to trigger daemon behavior call getRunningDaemon() to obtain the singleton and invoke a method on it.
Lifecycle
4 methods
| Method | Signature | Notes |
start | (): void | Boots the daemon: runs guard check, seeds config, starts the tick interval. |
stop | (): void | Clears the tick interval. Does not cancel in-flight workers. |
tick | (): Promise<void> | Single poll cycle execution, exposed for testing. |
cycle | (): Promise<void> | Full 13-step reconciliation loop: lifecycle poll, claim worker, CI health, repo snapshot, and more. |
Workers
4 methods
| Method | Signature | Notes |
startWorker | (id: string): Promise<void> | Resumes a paused worker by transitioning it back to running state. |
pauseWorker | (id: string): Promise<void> | Signals the worker to pause at its next safe checkpoint. |
restartWorker | (id: string): Promise<void> | Cancels and re-enqueues the worker from the beginning of its current phase. |
cancelWorker | (id: string): Promise<void> | Aborts the worker, cleans up the worktree, and marks it cancelled. |
Issues
5 methods
| Method | Signature | Notes |
startIssue | (repoId, issue: {number, title, htmlUrl, issueSource?}): Promise<void> | Creates a worker row and enqueues immediate implementation. |
returnIssueToBacklog | (repoId, issueNumber, issueSource?): Promise<void> | Removes the issue from the ready queue and cancels any active worker. |
setIssueReady | (repoId, issueNumber, ready, issueSource?): Promise<void> | Adds or removes the issue from the ready queue. |
reorderReadyIssue | (repoId, input: {issueNumber, toIndex, issueSource?}): Promise<void> | Moves the issue to a new position in the ready queue. |
retryIssue | (repoId, issueNumber, issueSource?): Promise<void> | Resets a failed worker and re-enqueues the issue for another attempt. |
PRs
5 methods
| Method | Signature | Notes |
mergePr | (repoId, prNumber): Promise<void> | Initiates squash merge via GitHub API. |
closePr | (repoId, prNumber): Promise<void> | Closes the PR without merging and transitions the worker to cancelled. |
reviewPr | (repoId, prNumber): Promise<void> | Triggers a Claude Code review skill run on the open PR. |
addressPr | (repoId, prNumber): Promise<void> | Triggers an address-comments phase for the PR. |
mergeWorker | (workerId): Promise<void> | Manually merges a worker that is waiting in the merge queue. |
Admin
8 methods + property
| Method | Signature | Notes |
overrideToMerged | (workerId): Promise<void> | Force-marks a worker as merged, skipping GitHub state checks. |
addRepo | (input: {slug, path, baseBranch?}): Promise<void> | Registers a new watched repo and seeds its initial snapshot. |
removeRepo | (repoId): Promise<void> | Unregisters a repo, cancels all its workers, and deletes worktrees. |
refreshRepoSnapshot | (): Promise<void> | Forces an immediate GitHub poll for all watched repos. |
fixBaseCi | (repoId): Promise<void> | Dispatches the fix-base-CI skill to repair failing base branch checks. |
syncBranch | (repoId): Promise<void> | Rebases an open worker PR onto the latest base branch HEAD. |
enableGuards | (): Promise<void> | Writes the guard-passed state to the DB after the setup wizard completes. |
wipeDatabase | (): Promise<void> | Drops all rows except Repo config. Irreversible. |
inFlight | Map<string, Promise<void>> | Property - live map of worker IDs to their running promises. Used by the runner registry to prevent double-spawning. |
Adding a new daemon operation: Add it to the Daemon interface in src/server/daemon/types.ts first, then implement in the appropriate ops/*.ts file. Wire the implementation into the main class in src/server/daemon/index.ts. The Server Action then calls it via getRunningDaemon().yourNewMethod().