Skip to main content
Sign in →

REST API Reference

Complete endpoint reference for the ShieldAgent management API. Base URL: https://api.shieldagent.io (self-hosted: https://api.shieldagent.io)

Authentication

All endpoints (except those marked public) require a JWT Bearer token in the Authorization header. Tokens are obtained via /auth/login or /auth/signup.

Example
curl https://api.shieldagent.io/tenants \
  -H 'Authorization: Bearer <your-jwt>' \
  -H 'Content-Type: application/json'

Error Format

All error responses follow a consistent JSON structure. Validation errors (400) include field-level details via Zod.

Error response
{
  "error": "Validation failed",
  "message": "Invalid request body",
  "issues": [
    { "path": ["name"], "message": "Required" },
    { "path": ["riskTier"], "message": "Invalid enum value" }
  ]
}
400Validation error — check issues array for field details
401Missing or invalid Authorization header
403Valid token but insufficient RBAC permissions
404Resource not found
409Conflict — duplicate resource (e.g. email already exists)
429Rate limit exceeded — see Retry-After header

Pagination

List endpoints that support pagination accept limit and offset query parameters and return a pagination object:

Paginated response
{
  "data": [ ... ],
  "pagination": {
    "total": 142,
    "limit": 50,
    "offset": 0,
    "hasMore": true
  }
}

Authentication

POST
/auth/signup

Register a new tenant and admin user. Returns a JWT.

Auth:none (public)

Rate-limited to 5 requests/minute.

ParameterInTypeRequiredDescription
emailbodystringyesUser email address
passwordbodystringyesMinimum 8 characters
tenantNamebodystringyesOrganization name
Request body
{
  "email": "admin@acme.com",
  "password": "s3cure-passw0rd",
  "tenantName": "Acme Corp"
}
Response 201
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
  "tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}
POST
/auth/login

Authenticate with email and password. Returns a JWT.

Auth:none (public)

Rate-limited to 10 requests/minute. Returns 403 with SSORequired error if the account uses SSO.

ParameterInTypeRequiredDescription
emailbodystringyesUser email address
passwordbodystringyesUser password
Request body
{
  "email": "admin@acme.com",
  "password": "s3cure-passw0rd"
}
Response 200
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
  "tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}
GET
/auth/me

Get the currently authenticated user profile.

Auth:Bearer token
Response 200
{
  "id": "u_01abc...",
  "email": "admin@acme.com",
  "role": "tenant_admin",
  "createdAt": "2026-01-15T10:30:00.000Z",
  "tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}
POST
/auth/refresh-entitlements

Refresh JWT with current plan tier and entitlements.

Auth:Bearer token
Response 200
{
  "token": "eyJhbGciOiJIUzI1NiIs...",
  "user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
  "tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}

Tenants

POST
/tenants

Create a new tenant organization.

Auth:Bearer token|Permission:tenant:write
ParameterInTypeRequiredDescription
namebodystringyesTenant display name
planTierbodystringnoOne of: free, team, starter, pro, business, enterprise_cloud, enterprise_onprem. Defaults to free.
kmsKeyIdbodystringnoOptional KMS key for envelope encryption
Request body
{
  "name": "Acme Corp",
  "planTier": "pro"
}
Response 201
{
  "id": "t_01xyz...",
  "name": "Acme Corp",
  "planTier": "pro",
  "createdAt": "2026-04-24T12:00:00.000Z"
}
GET
/tenants

List tenants. Platform admins see all; others see only their own tenant.

Auth:Bearer token|Permission:tenant:read
Response 200
[
  {
    "id": "t_01xyz...",
    "name": "Acme Corp",
    "planTier": "pro",
    "createdAt": "2026-04-24T12:00:00.000Z"
  }
]
GET
/tenants/:tenantId

Get a single tenant by ID.

Auth:Bearer token|Permission:tenant:read
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
PUT
/tenants/:tenantId

Update tenant fields.

Auth:Bearer token|Permission:tenant:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
namebodystringnoUpdated tenant name
planTierbodystringnoNew plan tier
kmsKeyIdbodystringnoUpdated KMS key ID
DELETE
/tenants/:tenantId

Delete a tenant and all associated data.

Auth:Bearer token|Permission:tenant:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
Response 200
{ "deleted": true, "id": "t_01xyz..." }

Users

GET
/tenants/:tenantId/users

List users in a tenant with their role assignments.

Auth:Bearer token|Permission:user:read
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
Response 200
[
  {
    "id": "u_01abc...",
    "email": "admin@acme.com",
    "role": "tenant_admin",
    "active": true,
    "createdAt": "2026-01-15T10:30:00.000Z"
  }
]
POST
/tenants/:tenantId/users/invite

Invite a new user to the tenant.

Auth:Bearer token|Permission:user:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
emailbodystringyesEmail address of the user to invite
passwordbodystringyesInitial password (min 8 characters)
rolebodystringnoOne of: tenant_admin, security_operator, auditor, aiops_engineer, viewer. Default: viewer
Request body
{
  "email": "analyst@acme.com",
  "password": "init-pass-123",
  "role": "security_operator"
}
Response 201
{
  "id": "u_02def...",
  "email": "analyst@acme.com",
  "role": "security_operator",
  "active": true,
  "createdAt": "2026-04-24T14:00:00.000Z"
}
PATCH
/tenants/:tenantId/users/:userId

Update a user's role or active status.

Auth:Bearer token|Permission:user:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
userIdpathuuidyesUser UUID
rolebodystringnoNew role assignment
activebodybooleannoSet false to deactivate
DELETE
/tenants/:tenantId/users/:userId

Remove a user from the tenant. Users cannot delete themselves.

Auth:Bearer token|Permission:user:delete
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
userIdpathuuidyesUser UUID
GET
/roles

List all available roles with their permissions.

Auth:Bearer token
Response 200
[
  {
    "id": "role_01...",
    "name": "security_operator",
    "scope": "tenant",
    "description": "Can triage incidents, manage alert rules, view audit logs",
    "isSystem": true,
    "permissions": ["incident:triage", "alert:write", "audit:read"]
  }
]

Agents

POST
/tenants/:tenantId/agents

Register a new AI agent. Returns an agent key for proxy authentication.

Auth:Bearer token|Permission:agent:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
namebodystringyesAgent display name
descriptionbodystringnoAgent purpose description
riskTierbodystringnoInitial risk tier: low, medium, high, critical
shadowModebodybooleannoStart in shadow mode (log only, never block). Default: false
Request body
{
  "name": "code-assistant",
  "description": "GitHub PR review agent",
  "riskTier": "medium"
}
Response 201
{
  "id": "agt_01HXYZ...",
  "name": "code-assistant",
  "agentKey": "sa_live_...",
  "riskTier": "medium",
  "shadowMode": false,
  "createdAt": "2026-04-24T12:00:00.000Z"
}
GET
/tenants/:tenantId/agents

List all agents in a tenant.

Auth:Bearer token|Permission:agent:read
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
GET
/tenants/:tenantId/agents/:agentId

Get a single agent with full configuration.

Auth:Bearer token|Permission:agent:read
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
agentIdpathuuidyesAgent UUID
PATCH
/tenants/:tenantId/agents/:agentId

Update agent metadata (name, description, shadowMode, riskTier).

Auth:Bearer token|Permission:agent:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
agentIdpathuuidyesAgent UUID
namebodystringnoUpdated agent name
descriptionbodystringnoUpdated description
shadowModebodybooleannoToggle shadow mode
riskTierbodystringnoUpdated risk tier
DELETE
/tenants/:tenantId/agents/:agentId

Deregister an agent and revoke its key.

Auth:Bearer token|Permission:agent:delete
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
agentIdpathuuidyesAgent UUID
Response 200
{ "deleted": true, "id": "agt_01HXYZ..." }
POST
/tenants/:tenantId/agents/:agentId/rotate-key

Rotate the agent's API key. The old key is immediately revoked.

Auth:Bearer token|Permission:agent:write
Response 200
{
  "agentKey": "sa_live_NEW...",
  "rotatedAt": "2026-04-24T12:00:00.000Z"
}
PATCH
/tenants/:tenantId/agents/:agentId/security-config

Configure per-agent security detection settings.

Auth:Bearer token|Permission:agent:write
ParameterInTypeRequiredDescription
injectionDetectionEnabledbodybooleannoEnable ML injection detection
dlpEnabledbodybooleannoEnable DLP scanning
excessiveAgencyEnabledbodybooleannoEnable excessive agency detection
toolDriftEnabledbodybooleannoEnable tool drift monitoring
PATCH
/tenants/:tenantId/agents/:agentId/baseline-config

Configure baseline learning parameters.

Auth:Bearer token|Permission:agent:write
ParameterInTypeRequiredDescription
warmupDaysbodyintegernoDays before drift detection activates (default: 7)
sensitivityMultiplierbodynumbernoDrift sensitivity (0.5–3.0, default: 1.0)
POST
/tenants/:tenantId/agents/:agentId/lock

Suspend an agent. All tool calls will be blocked until unlocked.

Auth:Bearer token|Permission:agent:write
ParameterInTypeRequiredDescription
reasonbodystringnoReason for suspension (written to audit trail)
POST
/tenants/:tenantId/agents/:agentId/unlock

Reinstate a suspended agent.

Auth:Bearer token|Permission:agent:write
DELETE
/tenants/:tenantId/agents/:agentId/baseline

Reset an agent's behavioral baseline. Drift scoring restarts from zero.

Auth:Bearer token|Permission:agent:write
Response 200
{ "reset": true, "agentId": "agt_01HXYZ..." }

Policies

POST
/tenants/:tenantId/policies

Create a policy rule for a tenant, agent, or tool.

Auth:Bearer token|Permission:policy:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
agentIdbodyuuidnoScope to a specific agent (omit for tenant-wide)
toolNamebodystringyesTool pattern to match (supports wildcards)
actionbodystringyesallow, deny, or shadow
conditionsbodyobjectnoOptional condition object (method, path, param matchers)
prioritybodyintegernoEvaluation priority (lower = first). Default: 100.
Request body
{
  "agentId": "agt_01HXYZ...",
  "toolName": "rest:stripe",
  "action": "deny",
  "conditions": { "method": "DELETE" }
}
Response 201
{
  "id": "pol_01...",
  "toolName": "rest:stripe",
  "action": "deny",
  "conditions": { "method": "DELETE" },
  "createdAt": "2026-04-24T12:00:00.000Z"
}
GET
/tenants/:tenantId/policies

List active policies for a tenant, optionally filtered by agent.

Auth:Bearer token|Permission:policy:read
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
agentIdqueryuuidnoFilter by agent
GET
/tenants/:tenantId/policies/:policyId

Get a single policy by ID.

Auth:Bearer token|Permission:policy:read
PUT
/tenants/:tenantId/policies/:policyId

Replace a policy rule.

Auth:Bearer token|Permission:policy:write
PATCH
/tenants/:tenantId/policies/:policyId

Partially update a policy rule.

Auth:Bearer token|Permission:policy:write
DELETE
/tenants/:tenantId/policies/:policyId

Delete a policy rule.

Auth:Bearer token|Permission:policy:delete
Response 200
{ "deleted": true, "id": "pol_01..." }
POST
/tenants/:tenantId/policies/evaluate

Dry-run: evaluate policies against a hypothetical tool call without writing to audit trail.

Auth:Bearer token|Permission:policy:read
ParameterInTypeRequiredDescription
agentIdbodyuuidnoAgent UUID to evaluate against
toolNamebodystringyesTool name to test
paramsbodyobjectnoTool parameters
Response 200
{
  "decision": "deny",
  "matchedPolicy": { "id": "pol_01...", "toolName": "rest:stripe", "action": "deny" },
  "reason": "Matched deny rule for DELETE on rest:stripe"
}
GET
/tenants/:tenantId/policies/templates

List available built-in policy templates.

Auth:Bearer token|Permission:policy:read

Policy Templates

GET
/policy-templates

List all available built-in policy templates.

Auth:Bearer token|Permission:policy:read
Response 200
[
  {
    "id": "pii-protection",
    "name": "PII Protection",
    "description": "Block tool calls that expose PII fields",
    "policyCount": 4
  }
]
GET
/policy-templates/:templateId

Get a single template with all policy definitions.

Auth:Bearer token|Permission:policy:read
ParameterInTypeRequiredDescription
templateIdpathstringyesTemplate slug (e.g. pii-protection)
POST
/tenants/:tenantId/policy-templates/:templateId/apply

Apply a template — creates all its policies in the tenant.

Auth:Bearer token|Permission:policy:write
ParameterInTypeRequiredDescription
tenantIdpathuuidyesTenant UUID
templateIdpathstringyesTemplate slug
agentIdbodyuuidnoScope policies to a specific agent (omit for tenant-wide)
Response 200
{
  "templateName": "pii-protection",
  "policiesCreated": 4,
  "policyIds": ["pol_01...", "pol_02...", "pol_03...", "pol_04..."]
}
DELETE
/tenants/:tenantId/policy-templates/:templateId/remove

Remove all policies that were applied from a template.

Auth:Bearer token|Permission:policy:delete
Response 200
{ "removed": 4, "templateName": "pii-protection" }
GET
/tenants/:tenantId/policy-templates/applied

List templates that have been applied to this tenant.

Auth:Bearer token|Permission:policy:read

Incidents

GET
/tenants/:tenantId/incidents

List incidents with filtering by status, severity, and agent.

Auth:Bearer token|Permission:incident:read
ParameterInTypeRequiredDescription
statusquerystringnoFilter: open, investigating, resolved
severityquerystringnoFilter: low, medium, high, critical
agentIdqueryuuidnoFilter by agent
limitqueryintegernoMax results (default 50, max 500)
offsetqueryintegernoPagination offset
POST
/tenants/:tenantId/incidents

Open a new incident manually.

Auth:Bearer token|Permission:incident:write
ParameterInTypeRequiredDescription
agentIdbodyuuidnoRelated agent
titlebodystringyesIncident title
severitybodystringyeslow, medium, high, or critical
typebodystringnoinjection, drift, policy_violation, anomaly, or manual
databodyobjectnoArbitrary incident context data
Response 201
{
  "id": "inc_01...",
  "title": "Prompt injection detected",
  "severity": "critical",
  "status": "open",
  "createdAt": "2026-04-24T12:00:00.000Z"
}
GET
/tenants/:tenantId/incidents/:incidentId

Get a single incident with full audit context.

Auth:Bearer token|Permission:incident:read
PATCH
/tenants/:tenantId/incidents/:incidentId

Update incident status or severity.

Auth:Bearer token|Permission:incident:triage
ParameterInTypeRequiredDescription
statusbodystringnoopen, investigating, or resolved
severitybodystringnoUpdated severity
resolutionbodystringnoResolution notes (required when status = resolved)
GET
/tenants/:tenantId/incidents/count

Get incident counts grouped by status and severity.

Auth:Bearer token|Permission:incident:read
Response 200
{
  "total": 42,
  "byStatus": { "open": 12, "investigating": 5, "resolved": 25 },
  "bySeverity": { "critical": 3, "high": 8, "medium": 18, "low": 13 }
}
GET
/tenants/:tenantId/incidents/:incidentId/audit

List audit events linked to an incident.

Auth:Bearer token|Permission:incident:read

Audit Trail

GET
/tenants/:tenantId/audit

List audit events with filtering, pagination, and optional Merkle proof.

Auth:Bearer token|Permission:audit:read
ParameterInTypeRequiredDescription
agentIdqueryuuidnoFilter by agent
toolquerystringnoFilter by tool name
outcomequerystringnoFilter: allow, block, shadow
fromqueryISO8601noStart timestamp
toqueryISO8601noEnd timestamp
limitqueryintegernoMax results (default 100, max 1000)
offsetqueryintegernoPagination offset
Response 200 (excerpt)
{
  "data": [
    {
      "id": "evt_01...",
      "agentId": "agt_01HXYZ...",
      "tool": "read_file",
      "outcome": "block",
      "riskScore": 0.87,
      "decision": "injection_detected",
      "timestamp": "2026-04-24T12:00:00.000Z",
      "merkleHash": "sha256:abc123..."
    }
  ],
  "pagination": { "total": 1420, "limit": 100, "offset": 0, "hasMore": true }
}
GET
/tenants/:tenantId/audit/:eventId

Get a single audit event with full payload and Merkle proof.

Auth:Bearer token|Permission:audit:read
POST
/tenants/:tenantId/audit/verify

Verify the Merkle integrity of a batch of audit events.

Auth:Bearer token|Permission:audit:read
ParameterInTypeRequiredDescription
eventIdsbodyuuid[]yesArray of event IDs to verify
Response 200
{
  "verified": true,
  "checkedCount": 50,
  "tamperDetected": false
}
GET
/tenants/:tenantId/audit/export

Stream audit events as NDJSON for bulk export.

Auth:Bearer token|Permission:audit:read

Response is streamed. Content-Type: application/x-ndjson. No pagination — returns all events in the window.

ParameterInTypeRequiredDescription
fromqueryISO8601noStart timestamp (required)
toqueryISO8601noEnd timestamp (required)
formatquerystringnondjson or json (default: ndjson)

Risk Scoring

GET
/tenants/:tenantId/risk/scores

Get current risk scores for all agents in a tenant.

Auth:Bearer token|Permission:risk:read
Response 200
{
  "data": [
    {
      "agentId": "agt_01HXYZ...",
      "agentName": "code-assistant",
      "currentScore": 0.67,
      "tier": "high",
      "trend": "increasing",
      "updatedAt": "2026-04-24T14:23:00Z"
    }
  ]
}
GET
/tenants/:tenantId/risk/scores/:agentId

Get detailed risk score with component breakdown for a specific agent.

Auth:Bearer token|Permission:risk:read
Response 200
{
  "agentId": "agt_01HXYZ...",
  "currentScore": 0.67,
  "tier": "high",
  "components": {
    "injectionScore": 0.12,
    "toolDriftScore": 0.71,
    "excessiveAgencyScore": 0.55,
    "anomalyScore": 0.84,
    "policyViolationRate": 0.03
  },
  "trend": "increasing",
  "trendDelta": 0.14,
  "updatedAt": "2026-04-24T14:23:00Z"
}
GET
/tenants/:tenantId/risk/scores/:agentId/history

Get risk score history for an agent (24h rolling window by default).

Auth:Bearer token|Permission:risk:read
ParameterInTypeRequiredDescription
windowquerystringnoTime window: 1h, 6h, 24h, 7d (default: 24h)
POST
/tenants/:tenantId/risk/scores/:agentId/recalculate

Force an immediate risk score recalculation for an agent.

Auth:Bearer token|Permission:risk:write
Response 200
{
  "agentId": "agt_01HXYZ...",
  "previousScore": 0.67,
  "newScore": 0.54,
  "recalculatedAt": "2026-04-24T14:30:00Z"
}
GET
/tenants/:tenantId/risk/config

Get risk enforcement configuration for the tenant.

Auth:Bearer token|Permission:risk:read
Response 200
{
  "monitorThreshold": 0.30,
  "blockThreshold": 0.80,
  "autoLockThreshold": 0.95,
  "humanReviewThreshold": 0.60
}
PATCH
/tenants/:tenantId/risk/config

Update risk enforcement thresholds for the tenant.

Auth:Bearer token|Permission:risk:write
ParameterInTypeRequiredDescription
monitorThresholdbodynumbernoScore at which monitoring alerts trigger (0.0–1.0)
blockThresholdbodynumbernoScore at which auto-block activates (0.0–1.0)
autoLockThresholdbodynumbernoScore at which agent is suspended (0.0–1.0)
humanReviewThresholdbodynumbernoScore at which human review is required (0.0–1.0)
GET
/tenants/:tenantId/risk/baselines/:agentId

Get the behavioral baseline for an agent.

Auth:Bearer token|Permission:risk:read
DELETE
/tenants/:tenantId/risk/baselines/:agentId

Reset an agent's behavioral baseline.

Auth:Bearer token|Permission:risk:write
Response 200
{ "reset": true, "agentId": "agt_01HXYZ..." }
POST
/tenants/:tenantId/risk/anomalies/analyze

Run an anomaly analysis on the last N hours of agent activity.

Auth:Bearer token|Permission:risk:read
ParameterInTypeRequiredDescription
agentIdbodyuuidnoAgent to analyze (omit for tenant-wide)
windowHoursbodyintegernoLookback window (default: 24)
Response 200
{
  "anomaliesDetected": true,
  "results": [
    {
      "anomalyType": "tool_burst",
      "anomalyScore": 0.91,
      "explanation": "Agent called 47 tools in 60 seconds (4.2σ above baseline)"
    }
  ]
}

Compliance

GET
/tenants/:tenantId/compliance/checklist

Get the current compliance posture with gap analysis.

Auth:Bearer token|Permission:compliance:read
Response 200
{
  "overallScore": 0.87,
  "passedChecks": 34,
  "totalChecks": 39,
  "sections": [
    {
      "id": "annex-iv-1",
      "title": "General Description",
      "status": "compliant",
      "evidence": ["agent-registry", "system-purpose"]
    },
    {
      "id": "annex-iv-4",
      "title": "Risk Management System",
      "status": "partial",
      "gaps": ["enforcement-thresholds-not-set-for-3-agents"]
    }
  ]
}
POST
/tenants/:tenantId/compliance/annex-iv/report

Generate an Annex IV PDF report from the audit trail.

Auth:Bearer token|Permission:compliance:read

Response is streamed. Content-Type: application/pdf. The PDF is generated from the immutable audit trail with Merkle integrity proofs.

ParameterInTypeRequiredDescription
periodStartbodyISO8601yesReport period start
periodEndbodyISO8601yesReport period end
formatbodystringnopdf or json (default: pdf)
GET
/tenants/:tenantId/compliance/reports

List previously generated compliance reports.

Auth:Bearer token|Permission:compliance:read
GET
/tenants/:tenantId/compliance/snapshots

Get compliance snapshots over time (for trending).

Auth:Bearer token|Permission:compliance:read
ParameterInTypeRequiredDescription
limitqueryintegernoMax snapshots (default 30)
GET
/tenants/:tenantId/compliance/iso42001/gap-analysis

ISO 42001 gap analysis against the agent inventory.

Auth:Bearer token|Permission:compliance:read
GET
/tenants/:tenantId/compliance/nist-ai-rmf/gap-analysis

NIST AI RMF gap analysis (Govern, Map, Measure, Manage functions).

Auth:Bearer token|Permission:compliance:read
POST
/tenants/:tenantId/compliance/regulatory-notifications

Create a regulatory incident notification draft (EU AI Act Art. 73).

Auth:Bearer token|Permission:compliance:write
ParameterInTypeRequiredDescription
incidentIdbodyuuidyesRelated incident UUID
notificationDeadlinebodyISO8601noRegulatory deadline (auto-calculated from incident date if omitted)

Alerts

GET
/tenants/:tenantId/alerts/rules

List alert rules.

Auth:Bearer token|Permission:alert:read
POST
/tenants/:tenantId/alerts/rules

Create an alert rule.

Auth:Bearer token|Permission:alert:write
ParameterInTypeRequiredDescription
namebodystringyesRule name
conditionbodystringyesCEL condition expression (e.g. riskScore >= 0.70)
severitybodystringyeslow, medium, high, or critical
channelsbodystring[]noDelivery channels: webhook, email, slack
webhookUrlbodystringnoWebhook delivery URL
agentIdbodyuuidnoScope to a specific agent
PATCH
/tenants/:tenantId/alerts/rules/:ruleId

Update an alert rule.

Auth:Bearer token|Permission:alert:write
DELETE
/tenants/:tenantId/alerts/rules/:ruleId

Delete an alert rule.

Auth:Bearer token|Permission:alert:delete
GET
/tenants/:tenantId/alerts/events

List fired alert events.

Auth:Bearer token|Permission:alert:read
ParameterInTypeRequiredDescription
limitqueryintegernoMax results (default 100, max 500)
fromqueryISO8601noStart timestamp

MCP Servers

POST
/tenants/:tenantId/mcp-servers

Register an MCP server for scanning and tool discovery.

Auth:Bearer token|Permission:mcp_server:write
ParameterInTypeRequiredDescription
namebodystringyesMCP server display name
urlbodystringyesMCP server URL or stdio command
transportbodystringnohttp-sse or stdio (default: http-sse)
scanOnRegisterbodybooleannoRun initial scan on registration (default: true)
Response 201
{
  "id": "mcp_01...",
  "name": "filesystem-server",
  "url": "http://localhost:8080",
  "transport": "http-sse",
  "createdAt": "2026-04-24T12:00:00.000Z"
}
GET
/tenants/:tenantId/mcp-servers

List registered MCP servers.

Auth:Bearer token|Permission:mcp_server:read
GET
/tenants/:tenantId/mcp-servers/:mcpServerId

Get a single MCP server with tool inventory.

Auth:Bearer token|Permission:mcp_server:read
PUT
/tenants/:tenantId/mcp-servers/:mcpServerId

Update MCP server configuration.

Auth:Bearer token|Permission:mcp_server:write
DELETE
/tenants/:tenantId/mcp-servers/:mcpServerId

Deregister an MCP server.

Auth:Bearer token|Permission:mcp_server:delete
Response 200
{ "deleted": true, "id": "mcp_01..." }
POST
/tenants/:tenantId/mcp-servers/:mcpServerId/refresh-tools

Re-discover tools from the MCP server.

Auth:Bearer token|Permission:mcp_server:write
Response 200
{
  "toolsDiscovered": 12,
  "toolsAdded": 2,
  "toolsRemoved": 0,
  "refreshedAt": "2026-04-24T12:00:00.000Z"
}
POST
/tenants/:tenantId/mcp-servers/:mcpServerId/scan

Run a security scan on the MCP server's tools.

Auth:Bearer token|Permission:mcp_server:write
Response 200
{
  "scanId": "scan_01...",
  "status": "completed",
  "vulnerabilities": 1,
  "toolCount": 5,
  "scanDuration": 1240
}
GET
/tenants/:tenantId/mcp-servers/:mcpServerId/scans

Get scan history for an MCP server.

Auth:Bearer token|Permission:mcp_server:read
ParameterInTypeRequiredDescription
limitqueryintegernoMax results (default 20, max 100)
GET
/tenants/:tenantId/scans

Tenant-wide scan history across all MCP servers.

Auth:Bearer token|Permission:mcp_server:read
ParameterInTypeRequiredDescription
limitqueryintegernoMax results (default 50, max 200)

Reviews

Human-in-the-loop review queue for tool calls that require approval before execution.

GET
/tenants/:tenantId/reviews

List pending reviews with filtering and pagination.

Auth:Bearer token|Permission:review:read
ParameterInTypeRequiredDescription
statusquerystringnoFilter: pending, approved, denied
agentIdqueryuuidnoFilter by agent
limitqueryintegernoMax results (default 50, max 500)
offsetqueryintegernoPagination offset
GET
/tenants/:tenantId/reviews/count

Get review counts by status.

Auth:Bearer token|Permission:review:read
Response 200
{ "pending": 5, "approved": 120, "denied": 8 }
GET
/tenants/:tenantId/reviews/:reviewId

Get a single review with agent name.

Auth:Bearer token|Permission:review:read
POST
/tenants/:tenantId/reviews/:reviewId/decide

Approve or deny a pending review.

Auth:Bearer token|Permission:review:triage
ParameterInTypeRequiredDescription
decisionbodystringyesapproved or denied
commentbodystringnoOptional reviewer comment
Request body
{
  "decision": "approved",
  "comment": "Verified safe — one-time file access needed"
}

Notifications

GET
/tenants/:tenantId/notifications

List in-app notifications for the current user.

Auth:Bearer token
ParameterInTypeRequiredDescription
unreadOnlyquerybooleannoFilter to unread only
limitqueryintegernoMax results (default 50, max 200)
PATCH
/tenants/:tenantId/notifications/:id/read

Mark a single notification as read.

Auth:Bearer token
POST
/tenants/:tenantId/notifications/read-all

Mark all unread notifications as read.

Auth:Bearer token
Response 200
{ "marked": 12 }

Passports

Agent Passports provide verifiable identity cards for AI agents. Requires Business tier or above.

GET
/tenants/:tenantId/agents/:agentId/passport

Get an agent's passport with risk assessment, compliance status, and signature.

Auth:Bearer token|Permission:passport:read

Requires agent_passport feature entitlement (Business+ plan).

PATCH
/tenants/:tenantId/agents/:agentId/passport

Update passport display metadata.

Auth:Bearer token|Permission:passport:write
ParameterInTypeRequiredDescription
displayNamebodystringnoPublic display name
descriptionbodystringnoPublic description
avatarUrlbodystringnoAvatar image URL (SSRF-protected)
visibilitybodystringnoprivate, internal, or public
POST
/tenants/:tenantId/agents/:agentId/passport/refresh

Recompute and re-sign the passport with latest data.

Auth:Bearer token|Permission:passport:write
POST
/tenants/:tenantId/agents/:agentId/passport/publish

Publish the passport for external verification.

Auth:Bearer token|Permission:passport:write

Publishing as public requires elevated role (security_manager, tenant_admin, or platform_admin).

ParameterInTypeRequiredDescription
visibilitybodystringnopublic or internal (default: internal)
POST
/tenants/:tenantId/agents/:agentId/passport/unpublish

Unpublish a passport — sets visibility to private.

Auth:Bearer token|Permission:passport:write
GET
/public/passports/:tenantSlug/:agentSlug

View a published passport (public, unauthenticated).

Auth:none (public)

Rate-limited to 60 requests/minute per IP. Returns cached response (max-age 300s).

GET
/public/passports/:tenantSlug/:agentSlug/verify

Verify a passport's cryptographic signature (public, unauthenticated).

Auth:none (public)
Response 200
{
  "verified": true,
  "valid": true,
  "passportHash": "sha256:abc123...",
  "signature": "base64:...",
  "signedAt": "2026-04-24T12:00:00.000Z",
  "keyId": "key_01...",
  "publicKey": "-----BEGIN PUBLIC KEY-----..."
}
GET
/public/passports/:tenantSlug/:agentSlug/badge.svg

Render an embeddable SVG badge for the agent (public, unauthenticated).

Auth:none (public)

Rate-limited to 300 requests/minute per IP. Content-Type: image/svg+xml.

Billing

GET
/billing/status

Current plan tier and subscription status.

Auth:Bearer token|Permission:tenant:read
Response 200
{
  "planTier": "pro",
  "billingState": "active",
  "hasStripeCustomer": true,
  "hasSubscription": true
}
GET
/billing/entitlements

Feature entitlements and limits for the current plan.

Auth:Bearer token|Permission:tenant:read
Response 200
{
  "planTier": "pro",
  "billingState": "active",
  "entitlements": {
    "maxAgents": 50,
    "includedToolCalls": 100000,
    "retentionDays": 365,
    "features": ["agent_passport", "sso", "custom_policies"]
  }
}
GET
/billing/usage

Current month usage and plan limits.

Auth:Bearer token|Permission:tenant:read
Response 200
{
  "currentAgentCount": 12,
  "maxAgents": 50,
  "currentToolCalls": 45230,
  "includedToolCalls": 100000,
  "overageRate": 0.001,
  "billingPeriodStart": "2026-04-01T00:00:00.000Z",
  "billingPeriodEnd": "2026-04-30T23:59:59.999Z",
  "retentionDays": 365
}
POST
/billing/checkout

Create a Stripe Checkout session for plan upgrade.

Auth:Bearer token|Permission:tenant:write
ParameterInTypeRequiredDescription
tierbodystringyesTarget plan: free, team, starter, pro, business
successPathbodystringnoRedirect path after success
cancelPathbodystringnoRedirect path on cancel
Response 200
{ "checkoutUrl": "https://checkout.stripe.com/c/pay_..." }
POST
/billing/portal

Create a Stripe Customer Portal session for subscription management.

Auth:Bearer token|Permission:tenant:write
Response 200
{ "portalUrl": "https://billing.stripe.com/p/session_..." }

Export Configs

Configure automated audit trail export to S3, webhooks, or syslog destinations. Credentials are encrypted at rest (AES-256-GCM) and never returned in API responses.

POST
/tenants/:tenantId/export-configs

Create an export configuration.

Auth:Bearer token|Permission:export:write
ParameterInTypeRequiredDescription
namebodystringyesConfig display name
destinationTypebodystringyess3, webhook, or syslog
configbodyobjectyesDestination-specific config (bucket, url, host, etc.)
credentialsbodyobjectnoAuth credentials (encrypted at rest, never returned)
filtersbodyobjectnoEvent filters (agent, tool, outcome, etc.)
intervalSecondsbodyintegernoExport interval (30–86400 seconds)
formatbodystringnondjson or json (default: ndjson)
enabledbodybooleannoActive on creation (default: true)
Request body
{
  "name": "S3 Audit Export",
  "destinationType": "s3",
  "config": {
    "bucket": "acme-audit-logs",
    "region": "eu-west-1",
    "prefix": "shieldagent/"
  },
  "credentials": {
    "accessKeyId": "AKIA...",
    "secretAccessKey": "wJalr..."
  },
  "intervalSeconds": 300,
  "format": "ndjson"
}
GET
/tenants/:tenantId/export-configs

List export configs (credentials redacted).

Auth:Bearer token|Permission:export:read
PATCH
/tenants/:tenantId/export-configs/:configId

Update an export config (partial update, credentials redacted in response).

Auth:Bearer token|Permission:export:write
DELETE
/tenants/:tenantId/export-configs/:configId

Delete an export configuration.

Auth:Bearer token|Permission:export:delete
POST
/tenants/:tenantId/export-configs/:configId/test

Test the export adapter connection.

Auth:Bearer token|Permission:export:write
Response 200
{ "success": true, "latencyMs": 245 }

Verdict API

Enforcement responsibility

The Verdict API runs the full ShieldAgent security pipeline and returns a verdict. Your server code is responsible for enforcing that verdict — ShieldAgent does not forward or block traffic directly. If your code ignores a block verdict, the tool call executes anyway. All scan verdicts are recorded in the audit trail with source: "verdict_api"; anomaly detection can flag agents with 100% block verdicts but continued tool execution.

The Verdict API enables server-side scanning for customers who own and operate their own API or MCP server (Deployment Position E). Instead of routing traffic through the ShieldAgent proxy, your server submits the request payload to ShieldAgent, receives a security verdict, and enforces it locally. The agent's communication with your server is unchanged — no MCP messages are modified, no HTTP headers are added.

Auth model — tenant API key, not user JWT

Verdict API endpoints authenticate with a tenant-scoped API key (Bearer token), not the user JWT issued by /auth/login. Treat this key as a server-side secret — never expose it to agent clients.

Base URL (proxy service): https://proxy.shieldagent.io  |  Self-hosted: http://localhost:3100

POST
/tenants/:tenantId/scan

Submit a tool call or API request for security scanning. Returns a verdict (allow / block / human_review). Your server must enforce the verdict — ShieldAgent does not forward traffic.

Auth:Bearer token

Auth: Bearer <tenant-api-key>. Rate-limited per tenant and per agent (Redis-backed). An audit event is written on every call with source: "verdict_api". The same multi-stage pipeline as the inline proxy runs — forwarding is skipped.

ParameterInTypeRequiredDescription
tenantIdpathstring (uuid)yesYour tenant UUID
agentIdbodystring (uuid)noShieldAgent agent UUID. Optional — omit when your server cannot identify the caller (e.g. typical MCP server, which has no agent identity in the protocol). When provided the agent must belong to this tenant; cross-tenant IDs are rejected with 403. When omitted the pipeline runs with tenant-level policies only.
clientHintbodystringnoMCP clientInfo.name or similar client software identifier (e.g. "Claude Desktop"). Used for best-effort agent matching when agentId is unavailable: if exactly one registered agent matches, per-agent policies apply; otherwise falls back to tenant-level. Ignored when agentId is provided.
toolNamebodystringyesName of the tool being called (e.g. "read_file", "api:POST:/payments")
paramsbodyobjectyesTool call parameters as a JSON object
include_findingsbodybooleannoRequest detailed findings in the response. Requires the verdictDetailedFindings tenant permission flag (off by default — see Response Tiering below). Without permission this field is ignored.
context.transportbody"mcp" | "rest" | "custom"noTransport protocol between agent and your server
context.sourceIpbodystringnoIP address of the agent. Used for per-IP rate limiting.
context.sessionIdbodystringnoSession identifier. Used for excessive agency detection across calls in the same session.
Request body
{
  "agentId": "a1b2c3d4-0000-0000-0000-000000000001",  // optional
  "clientHint": "Claude Desktop",                       // optional
  "toolName": "read_file",
  "params": { "path": "/etc/passwd" },
  "include_findings": false,
  "context": {
    "transport": "mcp",
    "sourceIp": "10.0.1.5",
    "sessionId": "sess-abc123"
  }
}
Response 200 — default tier (all callers)
{
  "action": "block",              // "allow" | "block" | "human_review"
  "reason": "Security threat detected",
  "riskScore": 87,
  "auditEventId": "evt-a1b2c3d4-0000-0000-0000-000000000001",
  "reviewId": null                // set when action is "human_review"
}

Response tiering include_findings: true + verdictDetailedFindings tenant permission

Detailed findings are off by default. The default response deliberately omits scanner names, detection patterns, and strategy details to prevent iterative evasion attacks (mirrors the DLP findings model). Enable only for debugging or integration testing.

Response 200 — detailed tier
{
  "action": "block",
  "reason": "Prompt injection detected in tool arguments",
  "findings": [
    {
      "type": "injection",
      "severity": "critical",
      "detail": "Path traversal pattern detected",
      "scanner": "regex"
    }
  ],
  "riskScore": 87,
  "auditEventId": "evt-a1b2c3d4-...",
  "reviewId": null
}

Error responses

401Missing or invalid tenant API key
403agentId does not belong to this tenant (cross-tenant spoofing rejected)
429Rate limit exceeded — per-tenant or per-agent limit. See Retry-After header.

When to omit agentId

ScenarioagentIdPipeline behaviour
MCP server (typical)omitTenant-level policies only. Optionally pass clientHint from the MCP clientInfo.name handshake.
HTTP API with agent auth mappingprovideFull per-agent pipeline: policies, risk score, rate limits, baseline, approved tools.
HTTP API without agent mappingomitTenant-level policies only. Rate limiting applies per-tenant.
POST
/tenants/:tenantId/verdict-confirmations

Report whether a verdict was enforced by your server. Optional callback that closes the audit loop and satisfies EU AI Act Art. 9 enforcement evidence requirements. Tenants that never call this show as 'enforcement unknown' in compliance reports.

Auth:Bearer token

Not required — enforcement confirmation is voluntary. Contributes to the Verdict Enforcement Rate metric in Grafana. Call after executing or rejecting the tool call, not before.

ParameterInTypeRequiredDescription
tenantIdpathstring (uuid)yesYour tenant UUID
auditEventIdbodystring (uuid)yesThe auditEventId returned by POST /scan
executedbodybooleanyestrue if the tool call was executed (verdict was "allow" or human review approved); false if it was rejected (verdict was "block" or human review denied)
Request body
{
  "auditEventId": "evt-a1b2c3d4-0000-0000-0000-000000000001",
  "executed": false
}
Response 200
{ "recorded": true }

Health

GET
/healthz

Liveness probe. Returns service status and timestamp.

Auth:none (public)

Excluded from rate limiting. Use for Kubernetes liveness/readiness probes.

Response 200
{
  "status": "ok",
  "timestamp": "2026-04-24T12:00:00.000Z"
}

OpenAPI Specification

The full OpenAPI 3.1.0 spec is available for import into Postman, Insomnia, or any OpenAPI-compatible tool. See the OpenAPI Reference page for spec URLs and client generation instructions.

bash
# Serve Swagger UI locally
npx @redocly/cli preview-docs docs/openapi/shieldagent-api.yaml
REST API Reference | ShieldAgent