Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.crewship.ai/llms.txt

Use this file to discover all available pages before exploring further.

All endpoints require authentication and are workspace-scoped. Decision endpoints additionally require OWNER or ADMIN role. Enqueue is internal-only — it fires from harbormaster.Gate when an agent hits a rule-matching action. See the Harbor Master guide.

List approvals

GET /api/v1/approvals?status=pending&limit=50
Query parameters:
ParamTypeDefaultDescription
statusstringpendingOne of pending, approved, denied, timeout, cancelled, all. all removes the status filter.
limitinteger501-200.
Response: 200 OK
{
  "rows": [
    {
      "id": "req_01HXYZABCDEF",
      "workspace_id": "ws_123",
      "crew_id": "crw_backend",
      "agent_id": "agt_viktor",
      "mission_id": "MIS-42",
      "requested_by": "agt_viktor",
      "kind": "destructive_op",
      "reason": "rm -rf /data/*",
      "payload": { "tool": "Bash", "args": { "command": "rm -rf /data/*" } },
      "status": "pending",
      "decided_by": null,
      "decided_at": null,
      "decision_comment": null,
      "timeout_at": "2026-04-17T11:23:41Z",
      "created_at": "2026-04-17T10:23:41Z"
    }
  ],
  "status": "pending",
  "count": 1
}
FieldTypeDescription
rows[].kindstringtool_call, cost_threshold, destructive_op, target_environment, custom.
rows[].statusstringSee Status values above.
rows[].payloadobjectTool call context (tool, args, plus any rule-specific fields).
rows[].timeout_atstring?RFC3339 deadline; the sweeper flips past-due rows to timeout.

Get approval

GET /api/v1/approvals/{id}
Returns the full request object (same schema as list rows). Errors:
StatusCondition
401No workspace.
404ID not found or belongs to another workspace.

Decide

POST /api/v1/approvals/{id}/decide
Auth: OWNER or ADMIN only. 403 for any other role. Request body:
{
  "status": "approved",
  "comment": "reviewed with staging validation"
}
FieldTypeRequiredDescription
statusstringYesapproved or denied. Any other value = 400.
commentstringNoFree-form decision rationale. Stored in approvals_queue.decision_comment.
Response: 200 OK
{
  "status": "approved",
  "decided_by": "user_123"
}
Errors:
StatusCondition
400Bad JSON, missing/invalid status.
401Not authenticated.
403Not OWNER/ADMIN.
404Request not found.
409Request already decided (status != pending).

Reset auto-tuning

POST /api/v1/approvals/reset-auto-tuning
Harbor Master observes operator decisions over time and auto-tunes its rule confidences (a denied request that would have auto-approved next time is a calibration signal). This endpoint resets that learned state to defaults — useful after a major change in policy or after a misconfiguration polluted the auto-tuning model. Auth: OWNER or ADMIN only. Request body: none, or {}. Response: 200 OK
{
  "ok": true,
  "reset_at": "2026-04-30T11:42:18Z",
  "rules_reset": 14
}
rules_reset is the number of rule rows whose tuning state was cleared. Idempotent — calling twice in a row returns rules_reset: 0 on the second call. Errors: 401 not authenticated; 403 wrong role; 500 DB error. This does not affect already-decided approval rows, journal history, or the rule definitions themselves — only the per-rule confidence that drives auto-mode (async/sync/required) selection.

Journal side-effects

Every write emits a journal entry:
ActionEntry
Enqueueapproval.requested (info)
Decide approvedapproval.granted (info)
Decide deniedapproval.denied (warn)
Timeout sweepapproval.timeout (warn)
Cancel (internal)approval.cancelled (notice)
See Crew Journal for payload shapes.