Skip to Content
DojOps — AI DevOps Automation Engine. Learn more →
UsageAPI Reference

API Reference

DojOps exposes a REST API via Express with 19 endpoints covering generation, planning, diagnostics, scanning, chat, metrics, and history. Start the server with dojops serve.


Base URL

http://localhost:3000/api # Backward-compatible (no version prefix) http://localhost:3000/api/v1 # Versioned (includes X-API-Version: 1 header)

Both prefixes route to the same handlers. The /api/v1/ prefix sets the X-API-Version: 1 response header for clients that need explicit version negotiation. The port is configurable via --port flag or DOJOPS_API_PORT environment variable.


Authentication

The API supports optional API key authentication via Bearer token or X-API-Key header:

# Bearer token curl -H "Authorization: Bearer <your-api-key>" http://localhost:3000/api/agents # X-API-Key header curl -H "X-API-Key: <your-api-key>" http://localhost:3000/api/agents

Generating credentials:

dojops serve credentials # Generates API key, saves to ~/.dojops/server.json

When an API key is configured (via DOJOPS_API_KEY env var or ~/.dojops/server.json), all endpoints except the minimal GET /api/health response require authentication. Without a configured API key, all endpoints are accessible without credentials.

Key comparison uses crypto.timingSafeEqual to prevent timing attacks.


Endpoints

Health

GET /api/health

Returns server status and auth requirement. When authenticated (or when auth is disabled), returns full diagnostic payload.

Response (unauthenticated, auth enabled):

{ "status": "ok", "authRequired": true, "timestamp": "2026-01-15T10:30:00.000Z" }

Response (authenticated or auth disabled):

{ "status": "ok", "authRequired": false, "provider": "openai", "tools": ["github-actions", "terraform", "kubernetes", ...], "metricsEnabled": true, "timestamp": "2026-01-15T10:30:00.000Z" }

The authRequired field indicates whether the server has API key authentication configured. When authRequired is true, unauthenticated callers receive only the minimal payload (status, authRequired, timestamp) to prevent information leakage.


Generation

POST /api/generate

Agent-routed LLM generation. DojOps routes the prompt to the most relevant specialist agent.

Request:

{ "prompt": "Create a Kubernetes deployment for nginx", "temperature": 0.7 }
FieldTypeRequiredDescription
promptstringYesNatural language prompt
temperaturenumberNoLLM temperature (0-1)

Response:

{ "content": "apiVersion: apps/v1\nkind: Deployment\n...", "agent": { "name": "kubernetes-specialist", "domain": "container-orchestration", "confidence": 0.92, "reason": "Matched keywords: kubernetes, deployment, nginx" }, "historyId": "gen-a1b2c3d4" }

curl:

curl -X POST http://localhost:3000/api/generate \ -H "Content-Type: application/json" \ -d '{"prompt": "Create a Kubernetes deployment for nginx", "temperature": 0.7}'

Planning

POST /api/plan

Decompose a goal into a dependency-aware task graph with optional execution.

Request:

{ "goal": "Set up CI/CD for a Node.js app", "execute": false, "autoApprove": false }
FieldTypeRequiredDescription
goalstringYesGoal to decompose
executebooleanNoExecute after planning (default: false)
autoApprovebooleanNoAuto-approve execution (default: false)

Response:

{ "graph": { "nodes": [ { "id": "1", "tool": "github-actions", "input": {...}, "deps": [] }, { "id": "2", "tool": "dockerfile", "input": {...}, "deps": ["1"] } ] }, "result": null, "historyId": "plan-e5f6g7h8" }

curl:

curl -X POST http://localhost:3000/api/plan \ -H "Content-Type: application/json" \ -d '{"goal": "Set up CI/CD for a Node.js app", "execute": false}'

Diagnostics

POST /api/debug-ci

Diagnose CI/CD log failures. Returns structured diagnosis with error type, root cause, affected files, and suggested fixes.

Request:

{ "log": "ERROR: npm ERR! ERESOLVE unable to resolve dependency tree" }
FieldTypeRequiredDescription
logstringYesCI/CD log output

Response:

{ "diagnosis": { "errorType": "dependency-resolution", "rootCause": "Conflicting peer dependency versions", "affectedFiles": ["package.json"], "fixes": [ { "description": "Use --legacy-peer-deps flag", "command": "npm install --legacy-peer-deps", "confidence": 0.85 } ] }, "historyId": "debug-i9j0k1l2" }

curl:

curl -X POST http://localhost:3000/api/debug-ci \ -H "Content-Type: application/json" \ -d '{"log": "ERROR: npm ERR! ERESOLVE unable to resolve dependency tree"}'

POST /api/diff

Analyze infrastructure diffs for risk, cost impact, security implications, and recommendations.

Request:

{ "diff": "+ resource \"aws_s3_bucket\" \"main\" { bucket = \"my-bucket\" }", "before": "optional previous state", "after": "optional new state" }
FieldTypeRequiredDescription
diffstringYesInfrastructure diff output
beforestringNoPrevious state context
afterstringNoNew state context

Response:

{ "analysis": { "riskLevel": "low", "costImpact": "minimal", "securityImpact": "none", "rollbackComplexity": "simple", "recommendations": ["Enable bucket versioning", "Add encryption"] }, "historyId": "diff-m3n4o5p6" }

curl:

curl -X POST http://localhost:3000/api/diff \ -H "Content-Type: application/json" \ -d '{"diff": "+ resource \"aws_s3_bucket\" \"main\" { bucket = \"my-bucket\" }"}'

Security Scanning

POST /api/scan

Run security scanners against a project directory.

Request:

{ "target": "/path/to/project", "scanType": "all" }
FieldTypeRequiredDescription
targetstringNoProject path (defaults to cwd)
scanTypestringNoall (default), security, deps, iac, sbom

Response:

{ "id": "scan-q7r8s9t0", "projectPath": "/path/to/project", "timestamp": "2026-01-15T10:30:00.000Z", "scanType": "all", "findings": [ { "id": "npm-1", "tool": "npm-audit", "severity": "HIGH", "category": "DEPENDENCY", "message": "prototype-pollution in lodash <4.17.21", "recommendation": "Upgrade lodash to >=4.17.21", "autoFixAvailable": true } ], "summary": { "total": 5, "critical": 0, "high": 2, "medium": 2, "low": 1 }, "scannersRun": ["npm-audit", "trivy", "gitleaks"], "scannersSkipped": ["pip-audit: no Python project detected"], "durationMs": 3200, "historyId": "scan-q7r8s9t0" }

curl:

curl -X POST http://localhost:3000/api/scan \ -H "Content-Type: application/json" \ -d '{"scanType": "security"}'

Chat

POST /api/chat

Send a message to a chat session. Creates a new session if sessionId is not provided.

Request:

{ "sessionId": "chat-a1b2c3d4", "message": "How should I set up Terraform state management?", "agent": "terraform-specialist" }
FieldTypeRequiredDescription
messagestringYesUser message
sessionIdstringNoExisting session ID (creates new if omitted)
agentstringNoPin to a specialist agent

Response:

{ "content": "For Terraform state management, I recommend...", "agent": "terraform-specialist", "sessionId": "chat-a1b2c3d4" }

curl:

curl -X POST http://localhost:3000/api/chat \ -H "Content-Type: application/json" \ -d '{"message": "How should I set up Terraform state management?"}'

POST /api/chat/sessions

Create a new chat session.

Request:

{ "name": "infra-planning", "mode": "INTERACTIVE" }
FieldTypeRequiredDescription
namestringNoSession name
modestringNoINTERACTIVE (default) or DETERMINISTIC

Response (201):

{ "id": "chat-a1b2c3d4", "name": "infra-planning", "createdAt": "2026-01-15T10:30:00.000Z", "updatedAt": "2026-01-15T10:30:00.000Z", "mode": "INTERACTIVE", "messages": [], "metadata": { "totalTokensEstimate": 0, "messageCount": 0 } }

curl:

curl -X POST http://localhost:3000/api/chat/sessions \ -H "Content-Type: application/json" \ -d '{"name": "infra-planning"}'

GET /api/chat/sessions

List all active chat sessions, sorted by most recently updated.

Response:

[ { "id": "chat-a1b2c3d4", "name": "infra-planning", "updatedAt": "2026-01-15T10:30:00.000Z", "mode": "INTERACTIVE", "metadata": { "messageCount": 12 } } ]

curl:

curl http://localhost:3000/api/chat/sessions

GET /api/chat/sessions/:id

Get a session’s full state by ID.

curl:

curl http://localhost:3000/api/chat/sessions/chat-a1b2c3d4

DELETE /api/chat/sessions/:id

Delete a chat session.

curl:

curl -X DELETE http://localhost:3000/api/chat/sessions/chat-a1b2c3d4

Agents

GET /api/agents

List all specialist agents (built-in + custom) with their domains, descriptions, keywords, and type.

Response:

[ { "name": "terraform-specialist", "domain": "infrastructure", "description": "Expert in Terraform, HCL, modules, state management...", "keywords": ["terraform", "infrastructure", "iac", "hcl", ...], "type": "built-in" }, { "name": "sre-specialist", "domain": "site-reliability", "description": "SRE specialist for incident response and reliability", "keywords": ["sre", "incident", "reliability", ...], "type": "custom" } ]

curl:

curl http://localhost:3000/api/agents

History

GET /api/history

List execution history with optional filtering.

Query Parameters:

ParamTypeDescription
typestringFilter: generate, plan, debug-ci, diff, scan, chat
limitnumberMax entries to return

Response:

{ "entries": [...], "count": 42 }

curl:

curl "http://localhost:3000/api/history?type=generate&limit=10"

GET /api/history/:id

Get a single history entry by ID.

curl:

curl http://localhost:3000/api/history/gen-a1b2c3d4

DELETE /api/history

Clear all execution history.

curl:

curl -X DELETE http://localhost:3000/api/history

Metrics

Metrics endpoints are only available when the server has access to a .dojops/ project directory (auto-detected by the CLI serve command).

GET /api/metrics

Full dashboard metrics combining overview, security, and audit data.

curl:

curl http://localhost:3000/api/metrics

GET /api/metrics/overview

Plan, execution, and scan aggregates.

Response:

{ "totalPlans": 15, "totalExecutions": 12, "successRate": 0.83, "avgExecutionTimeMs": 4500, "criticalFindings": 2, "highFindings": 5, "mostUsedCommands": {"generate": 20, "plan": 15, "scan": 8}, "recentActivity": [...] }

curl:

curl http://localhost:3000/api/metrics/overview

GET /api/metrics/security

Scan findings, severity trends, and top issues.

Response:

{ "totalScans": 8, "severityBreakdown": {"critical": 2, "high": 5, "medium": 12, "low": 8}, "categoryBreakdown": {"SECURITY": 10, "DEPENDENCY": 8, "IAC": 5, "SECRETS": 4}, "findingsTrend": [...], "topIssues": [...], "scanHistory": [...] }

curl:

curl http://localhost:3000/api/metrics/security

GET /api/metrics/audit

Audit chain integrity and command distribution.

Response:

{ "totalEntries": 45, "chainIntegrity": true, "statusBreakdown": {"success": 38, "failure": 5, "cancelled": 2}, "commandDistribution": {"generate": 20, "apply": 12, "scan": 8, "plan": 5}, "timeline": [...] }

curl:

curl http://localhost:3000/api/metrics/audit

Error Responses

All endpoints return errors in a consistent format:

{ "error": "Validation failed", "details": "prompt is required" }

Common HTTP status codes:

StatusMeaning
200Success
201Created (new chat session)
400Bad request (validation failed)
401Unauthorized (missing or invalid API key)
403Forbidden (e.g., autoApprove without auth)
404Not found
500Internal server error

Request Validation

All POST endpoints validate request bodies against Zod schemas. Invalid requests return 400 with details:

{ "error": "Validation failed", "details": [{ "path": ["prompt"], "message": "Required" }] }

DojOps Hub API

The DojOps Hub  is a separate service with its own API for the tool marketplace. It uses a different authentication system from the local DojOps server.

Hub Authentication

The Hub supports two authentication methods:

MethodHeaderUse Case
API Token (Bearer)Authorization: Bearer dojops_...CLI tool publishing, programmatic access
Session Cookienext-auth.session-token=...Browser-based access (automatic via GitHub OAuth)

All authenticated endpoints accept both methods. The Bearer token is checked first; session cookie is the fallback.

Generating an API token:

  1. Sign in to the Hub with GitHub OAuth
  2. Go to Settings → API Tokens (/settings/tokens)
  3. Create a named token with an expiration (1 month, 3 months, or no expiration)
  4. Copy the raw token — it’s shown once and stored as a SHA-256 hash

Token format: dojops_ followed by 40 hex characters. Maximum 10 tokens per user.

Token Management Endpoints

Token CRUD endpoints require session authentication only (not Bearer) — a leaked token cannot create or list other tokens.

GET /api/tokens

List the current user’s API tokens.

Response:

{ "tokens": [ { "id": "clx1abc...", "name": "My laptop", "tokenPrefix": "dojops_a1b2c3", "expiresAt": "2026-06-01T00:00:00.000Z", "lastUsedAt": "2026-03-01T14:30:00.000Z", "createdAt": "2026-03-01T10:00:00.000Z" } ] }

POST /api/tokens

Create a new API token.

Request:

{ "name": "CI/CD pipeline", "expiration": "3months" }
FieldTypeRequiredDescription
namestringYesLabel for the token (max 50 chars)
expirationstringNo1month, 3months, or never (default: never)

Response (201):

{ "id": "clx1abc...", "name": "CI/CD pipeline", "tokenPrefix": "dojops_a1b2c3", "expiresAt": "2026-06-01T00:00:00.000Z", "createdAt": "2026-03-01T10:00:00.000Z", "rawToken": "dojops_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2" }

The rawToken field is only included in the creation response. It cannot be retrieved again.

DELETE /api/tokens/:id

Revoke a token. Only the token owner can delete it.

Response:

{ "deleted": true }

Package Publishing Endpoint

POST /api/packages

Publish a new package or version. Requires authentication (Bearer token or session).

Request: multipart/form-data

FieldTypeRequiredDescription
fileFileYes.dops file (max 1MB)
sha256stringNoClient-computed SHA-256 hash (publisher attestation)
changelogstringNoVersion changelog

curl example with Bearer token:

# Publish using an API token curl -X POST https://hub.dojops.ai/api/packages \ -H "Authorization: Bearer dojops_a1b2c3d4e5f6..." \ -F "file=@my-tool.dops" \ -F "sha256=$(sha256sum my-tool.dops | cut -d' ' -f1)" \ -F "changelog=Initial release"

Response (201 — new package):

{ "slug": "my-tool", "version": "1.0.0", "created": true }

Response (200 — new version of existing package):

{ "slug": "my-tool", "version": "1.1.0", "updated": true }

Hub Rate Limits

ActionLimitWindow
Publish package5per hour
Star/unstar30per minute
Post comment10per minute
Search60per minute
Create token5per hour