REST API

Manage agents, policies, and alerts programmatically. All endpoints require an API key with appropriate permissions.

Authentication

Pass your API key in the X-Rune-Key header:

curl https://your-convex.convex.site/v1/agents \
  -H "X-Rune-Key: rune_live_xxx"

API keys are created in Settings > API Keys in the dashboard. Keys can have scoped permissions (agents:write, alerts:write). Keys with no permissions set have full access (legacy behavior).

Base URL

All API routes are served from your Convex HTTP endpoint:

https://<your-deployment>.convex.site

Events

POST /v1/events

Ingest security events from the SDK. This is the primary ingestion endpoint used by Shield to send scan results and policy evaluations to the cloud.

Requestbash
curl -X POST https://events.runesec.dev/v1/events \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "event_id": "evt_abc123",
        "timestamp": "2025-01-15T10:30:00Z",
        "agent_id": "my-agent",
        "event_type": "tool_call",
        "direction": "outbound",
        "scan_result": {
          "risk_score": 0.95,
          "l1_result": "block",
          "threats_detected": [{"type": "prompt_injection"}]
        }
      }
    ]
  }'
Response 202json
{
  "accepted": 1
}

The SDK batches events automatically ( event_batch_size default: 50, event_flush_interval_seconds default: 5s). You do not need to call this endpoint directly.

Agents

GET /v1/agents

List all registered agents for your organization.

Requestbash
curl https://your-convex.convex.site/v1/agents \
  -H "X-Rune-Key: rune_live_xxx"
Response 200json
{
  "agents": [
    {
      "_id": "abc123",
      "agentId": "research-agent",
      "name": "Research Agent",
      "framework": "langchain",
      "status": "active",
      "tags": ["prod", "research"],
      "riskScore": 0.12,
      "eventCount": 1523,
      "blockCount": 3,
      "lastSeen": 1708905600000
    }
  ]
}

POST /v1/agents

Register a new agent. Requires agents:write permission.

Requestbash
curl -X POST https://your-convex.convex.site/v1/agents \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "support-agent",
    "name": "Customer Support Agent",
    "framework": "openai",
    "tags": ["prod", "support"]
  }'
Response 201json
{
  "id": "def456",
  "agentId": "support-agent"
}

Policies

GET /v1/policies

List all active policies for your organization.

Requestbash
curl https://your-convex.convex.site/v1/policies \
  -H "X-Rune-Key: rune_live_xxx"
Response 200json
{
  "policies": [
    {
      "_id": "pol123",
      "name": "block-prompt-injection",
      "version": 2,
      "active": true,
      "updatedAt": 1708905600000
    }
  ]
}

POST /v1/policies

Create a new policy. Requires policies:write permission. The YAML is validated and compiled before storage.

Requestbash
curl -X POST https://your-convex.convex.site/v1/policies \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production Security Policy",
    "yamlContent": "version: \"1.0\"\nrules:\n  - name: block-injection\n    scanner: prompt_injection\n    action: block\n    severity: critical"
  }'
Response 201json
{
  "id": "pol789",
  "name": "Production Security Policy"
}

POST /v1/policies/update

Update a policy's name or YAML content. Requires policies:write permission. Updating YAML bumps the version number and recompiles.

Requestbash
curl -X POST https://your-convex.convex.site/v1/policies/update \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "policyId": "pol789",
    "name": "Updated Policy Name",
    "yamlContent": "version: \"1.0\"\nrules: ..."
  }'
Response 200json
{"updated": true}

POST /v1/policies/toggle

Enable or disable a policy. Requires policies:write permission.

Requestbash
curl -X POST https://your-convex.convex.site/v1/policies/toggle \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"policyId": "pol789", "active": false}'
Response 200json
{"updated": true}

POST /v1/policies/delete

Permanently delete a policy. Requires policies:write permission.

Requestbash
curl -X POST https://your-convex.convex.site/v1/policies/delete \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"policyId": "pol789"}'
Response 200json
{"deleted": true}

POST /v1/policies/validate

Validate a policy YAML string without persisting it. Useful for CI/CD pipelines and editor integrations. Any valid API key can call this.

Requestbash
curl -X POST https://your-convex.convex.site/v1/policies/validate \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"yamlContent": "version: \"1.0\"\nrules:\n  - name: test\n    scanner: prompt_injection\n    action: block\n    severity: critical"}'
Response 200json
{
  "valid": true,
  "compiled": { "rules": [...] },
  "error": null
}

Alerts

GET /v1/alerts

List all open alerts for your organization.

Requestbash
curl https://your-convex.convex.site/v1/alerts \
  -H "X-Rune-Key: rune_live_xxx"
Response 200json
{
  "alerts": [
    {
      "_id": "alrt789",
      "severity": "critical",
      "alertType": "injection_detected",
      "title": "Prompt injection detected on research-agent",
      "status": "open",
      "agentId": "research-agent",
      "occurrences": 3
    }
  ]
}

POST /v1/alerts/update

Update an alert status. Requires alerts:write permission.

Requestbash
curl -X POST https://your-convex.convex.site/v1/alerts/update \
  -H "X-Rune-Key: rune_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "alertId": "alrt789",
    "status": "resolved",
    "note": "False alarm — test data"
  }'

Valid statuses: open, investigating, resolved, false_positive.

Setting status to false_positive automatically creates a false-positive pattern that feeds back to the SDK scanners as an allowlist entry.

Health Check

GET /health

No authentication required.

Requestbash
curl https://your-convex.convex.site/health
Response 200json
{
  "status": "ok",
  "timestamp": 1708905600000
}

Error Responses

StatusMeaning
401Invalid or missing API key
403API key lacks required permission
400Invalid request body or missing required fields
404Resource not found

All error responses return JSON with an error field:

{"error": "Invalid or missing API key"}

Rate Limits

API endpoints are rate-limited per organization:

Endpoint TypeLimit
Read endpoints (GET)100 requests/minute
Write endpoints (POST)30 requests/minute
Event ingestion (POST /v1/events)1,000 events/second

Rate-limited responses return 429 Too Many Requests with a Retry-After header.

Pagination

List endpoints support cursor-based pagination via cursor and limit query parameters:

curl "https://your-convex.convex.site/v1/alerts?limit=50&cursor=abc123" \
  -H "X-Rune-Key: rune_live_xxx"

Responses include a next_cursor field when more results are available. Omit cursor to start from the beginning. Default limit is 50, maximum is 200.

OpenAPI Spec

A machine-readable OpenAPI 3.1 specification is available for all v1 endpoints. Use it to generate client libraries or import into tools like Postman:

https://runesec.dev/openapi.yaml

MCP Server

All API endpoints are also available as MCP tools via the Rune MCP server. This lets Claude Code, Cursor, and Windsurf manage your security policies and triage alerts natively.

pip install "runesec[mcp]"
rune-mcp  # starts MCP server on stdio

See the MCP documentation for setup instructions and the full list of available tools.

Permissions

API keys can be scoped with fine-grained permissions. Keys with no permissions set have full access (legacy behavior).

PermissionGrants Access To
agents:writePOST /v1/agents
policies:writePOST /v1/policies, /v1/policies/update, /toggle, /delete
alerts:writePOST /v1/alerts/update

All read endpoints (GET) are accessible with any valid API key regardless of permissions.