Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Web API Endpoints

The NabaOS web dashboard exposes a REST API on the configured bind address (default: 127.0.0.1:8919). Start the server with:

nabaos start --web-only                        # default: 127.0.0.1:8919
nabaos start --web-only --bind 0.0.0.0:9000   # custom bind address

Authentication

If NABA_WEB_PASSWORD is set, all API endpoints (except auth endpoints) require a valid session token. Tokens are passed via the Authorization header:

Authorization: Bearer <token>

If NABA_WEB_PASSWORD is not set, the web dashboard is disabled.

Sessions expire after 24 hours by default (configurable via NABA_WEB_SESSION_TTL).


POST /api/auth/login

Authenticate and obtain a session token.

Request:

curl -X POST http://localhost:8919/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"password": "my-password"}'

Response (200):

{
  "token": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Response (401):

{
  "error": "Invalid password"
}

POST /api/auth/logout

Invalidate the current session.

Request:

curl -X POST http://localhost:8919/api/auth/logout \
  -H "Authorization: Bearer <token>"

Response: 204 No Content


GET /api/auth/status

Check whether authentication is required and whether the current token is valid.

Request:

curl http://localhost:8919/api/auth/status \
  -H "Authorization: Bearer <token>"

Response (200):

{
  "authenticated": true,
  "auth_required": true
}

Dashboard

GET /api/dashboard

Overview of the system: chain count, scheduled jobs, abilities, and cost summary.

Request:

curl http://localhost:8919/api/dashboard \
  -H "Authorization: Bearer <token>"

Response (200):

{
  "total_chains": 12,
  "total_scheduled_jobs": 3,
  "total_abilities": 47,
  "costs": {
    "total_spent_usd": 4.23,
    "total_saved_usd": 18.91,
    "savings_percent": 81.7,
    "total_llm_calls": 142,
    "total_cache_hits": 891,
    "total_input_tokens": 285400,
    "total_output_tokens": 98200
  }
}

Query

POST /api/query

Process a query through the full orchestrator pipeline.

Request:

curl -X POST http://localhost:8919/api/query \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"query": "check the price of NVDA"}'

Response (200):

{
  "tier": "Tier1",
  "intent_key": "check|price",
  "confidence": 0.95,
  "allowed": true,
  "latency_ms": 0.42,
  "description": "Fingerprint cache hit",
  "response_text": "NVDA is currently trading at $142.50",
  "nyaya_mode": "MODE 1",
  "security": {
    "credentials_found": 0,
    "injection_detected": false,
    "injection_confidence": 0.0,
    "was_redacted": false
  }
}

Chains

GET /api/chains

List all stored chain definitions.

Request:

curl http://localhost:8919/api/chains \
  -H "Authorization: Bearer <token>"

Response (200):

[
  {
    "chain_id": "check_weather",
    "name": "Check Weather",
    "description": "Fetch weather for a city and notify user",
    "trust_level": 3,
    "hit_count": 142,
    "success_count": 140,
    "created_at": "2026-01-15T10:30:00Z"
  }
]

Scheduling

GET /api/chains/schedule

List all scheduled jobs.

Request:

curl http://localhost:8919/api/chains/schedule \
  -H "Authorization: Bearer <token>"

Response (200):

[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "chain_id": "check_email",
    "interval_secs": 600,
    "enabled": true,
    "last_run_at": 1708012345,
    "last_output": "No new messages",
    "run_count": 42,
    "created_at": 1707500000
  }
]

POST /api/chains/schedule

Create a new scheduled job.

Request:

curl -X POST http://localhost:8919/api/chains/schedule \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "chain_id": "check_email",
    "interval": "10m",
    "params": {"folder": "inbox"}
  }'

Response (201):

{
  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

The interval field accepts human-readable durations: "30s", "10m", "1h".

DELETE /api/chains/schedule/{id}

Disable a scheduled job.

Request:

curl -X DELETE http://localhost:8919/api/chains/schedule/a1b2c3d4-e5f6-7890 \
  -H "Authorization: Bearer <token>"

Response: 204 No Content


Costs

GET /api/costs

Retrieve cost tracking data. Optionally filter by time range.

Request:

# All-time costs
curl http://localhost:8919/api/costs \
  -H "Authorization: Bearer <token>"

# Costs since a specific Unix timestamp (milliseconds)
curl "http://localhost:8919/api/costs?since=1708012345000" \
  -H "Authorization: Bearer <token>"

Response (200):

{
  "total_spent_usd": 4.23,
  "total_saved_usd": 18.91,
  "savings_percent": 81.7,
  "total_llm_calls": 142,
  "total_cache_hits": 891,
  "total_input_tokens": 285400,
  "total_output_tokens": 98200
}

Security

POST /api/security/scan

Scan text for credentials, PII, and prompt injection patterns.

Request:

curl -X POST http://localhost:8919/api/security/scan \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"text": "my api key is sk-ant-abc123 and SSN 123-45-6789"}'

Response (200):

{
  "credential_count": 1,
  "pii_count": 1,
  "types_found": ["api_key", "ssn"],
  "injection_detected": false,
  "injection_match_count": 0,
  "injection_max_confidence": 0.0,
  "injection_category": null,
  "redacted": "my api key is [REDACTED:api_key] and SSN [REDACTED:ssn]"
}

Abilities

GET /api/abilities

List all available abilities (built-in, plugin, subprocess, cloud).

Request:

curl http://localhost:8919/api/abilities \
  -H "Authorization: Bearer <token>"

Response (200):

[
  {
    "name": "data.fetch_url",
    "description": "Fetch content from a URL",
    "source": "built-in"
  },
  {
    "name": "files.read_psd",
    "description": "Read Adobe PSD files, extract layers and metadata",
    "source": "plugin"
  }
]

Constitution

GET /api/constitution

Retrieve the active constitution rules and available templates.

Request:

curl http://localhost:8919/api/constitution \
  -H "Authorization: Bearer <token>"

Response (200):

{
  "name": "default",
  "rules": [
    {
      "name": "block_destructive_keywords",
      "enforcement": "Block",
      "trigger_actions": [],
      "trigger_targets": [],
      "trigger_keywords": ["delete all", "rm -rf", "drop table", "format disk", "wipe", "destroy"],
      "reason": "Destructive operations require explicit confirmation"
    },
    {
      "name": "allow_check_actions",
      "enforcement": "Allow",
      "trigger_actions": ["check"],
      "trigger_targets": [],
      "trigger_keywords": [],
      "reason": "Read-only operations are safe"
    }
  ],
  "templates": [
    {
      "name": "default",
      "description": "General-purpose safety defaults",
      "rules_count": 6
    },
    {
      "name": "trading",
      "description": "Financial markets monitoring and trading",
      "rules_count": 3
    }
  ]
}

POST /api/constitution/check

Check a query against the active constitution.

Request:

curl -X POST http://localhost:8919/api/constitution/check \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"query": "delete all files"}'

Confirmation

POST /api/auth/confirm/{token}

Confirm a pending weblink confirmation token (used by the 2FA system for Telegram bot confirmations via web link).

Request:

curl -X POST http://localhost:8919/api/auth/confirm/abc123-token

Response (200):

{
  "confirmed": true
}

Health

GET /api/health

Health check endpoint. No authentication required.

Request:

curl http://localhost:8919/api/health

Response (200):

{
  "status": "ok"
}

Static Files

If the nyaya-web/dist/ directory exists (built SPA frontend), it is served as static files at the root path. All non-API routes fall back to index.html for client-side routing.

If the frontend is not built, a fallback HTML page is shown with instructions to build it.

Error Responses

All error responses follow the same format:

{
  "error": "Description of the error"
}

Common HTTP status codes:

CodeMeaning
200Success
201Created (new resource)
204No Content (success, no body)
400Bad Request (invalid input)
401Unauthorized (missing or invalid token)
500Internal Server Error