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.
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": "Validation failed",
"message": "Invalid request body",
"issues": [
{ "path": ["name"], "message": "Required" },
{ "path": ["riskTier"], "message": "Invalid enum value" }
]
}Pagination
List endpoints that support pagination accept limit and offset query parameters and return a pagination object:
{
"data": [ ... ],
"pagination": {
"total": 142,
"limit": 50,
"offset": 0,
"hasMore": true
}
}Authentication
/auth/signupRegister a new tenant and admin user. Returns a JWT.
Rate-limited to 5 requests/minute.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| body | string | yes | User email address | |
| password | body | string | yes | Minimum 8 characters |
| tenantName | body | string | yes | Organization name |
{
"email": "admin@acme.com",
"password": "s3cure-passw0rd",
"tenantName": "Acme Corp"
}{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
"tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}/auth/loginAuthenticate with email and password. Returns a JWT.
Rate-limited to 10 requests/minute. Returns 403 with SSORequired error if the account uses SSO.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| body | string | yes | User email address | |
| password | body | string | yes | User password |
{
"email": "admin@acme.com",
"password": "s3cure-passw0rd"
}{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
"tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}/auth/meGet the currently authenticated user profile.
{
"id": "u_01abc...",
"email": "admin@acme.com",
"role": "tenant_admin",
"createdAt": "2026-01-15T10:30:00.000Z",
"tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}/auth/refresh-entitlementsRefresh JWT with current plan tier and entitlements.
{
"token": "eyJhbGciOiJIUzI1NiIs...",
"user": { "id": "u_01abc...", "email": "admin@acme.com", "role": "tenant_admin" },
"tenant": { "id": "t_01xyz...", "name": "Acme Corp" }
}Tenants
/tenantsCreate a new tenant organization.
tenant:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| name | body | string | yes | Tenant display name |
| planTier | body | string | no | One of: free, team, starter, pro, business, enterprise_cloud, enterprise_onprem. Defaults to free. |
| kmsKeyId | body | string | no | Optional KMS key for envelope encryption |
{
"name": "Acme Corp",
"planTier": "pro"
}{
"id": "t_01xyz...",
"name": "Acme Corp",
"planTier": "pro",
"createdAt": "2026-04-24T12:00:00.000Z"
}/tenantsList tenants. Platform admins see all; others see only their own tenant.
tenant:read[
{
"id": "t_01xyz...",
"name": "Acme Corp",
"planTier": "pro",
"createdAt": "2026-04-24T12:00:00.000Z"
}
]/tenants/:tenantIdGet a single tenant by ID.
tenant:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
/tenants/:tenantIdUpdate tenant fields.
tenant:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| name | body | string | no | Updated tenant name |
| planTier | body | string | no | New plan tier |
| kmsKeyId | body | string | no | Updated KMS key ID |
/tenants/:tenantIdDelete a tenant and all associated data.
tenant:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
{ "deleted": true, "id": "t_01xyz..." }Users
/tenants/:tenantId/usersList users in a tenant with their role assignments.
user:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
[
{
"id": "u_01abc...",
"email": "admin@acme.com",
"role": "tenant_admin",
"active": true,
"createdAt": "2026-01-15T10:30:00.000Z"
}
]/tenants/:tenantId/users/inviteInvite a new user to the tenant.
user:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| body | string | yes | Email address of the user to invite | |
| password | body | string | yes | Initial password (min 8 characters) |
| role | body | string | no | One of: tenant_admin, security_operator, auditor, aiops_engineer, viewer. Default: viewer |
{
"email": "analyst@acme.com",
"password": "init-pass-123",
"role": "security_operator"
}{
"id": "u_02def...",
"email": "analyst@acme.com",
"role": "security_operator",
"active": true,
"createdAt": "2026-04-24T14:00:00.000Z"
}/tenants/:tenantId/users/:userIdUpdate a user's role or active status.
user:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| userId | path | uuid | yes | User UUID |
| role | body | string | no | New role assignment |
| active | body | boolean | no | Set false to deactivate |
/tenants/:tenantId/users/:userIdRemove a user from the tenant. Users cannot delete themselves.
user:delete| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| userId | path | uuid | yes | User UUID |
/rolesList all available roles with their permissions.
[
{
"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
/tenants/:tenantId/agentsRegister a new AI agent. Returns an agent key for proxy authentication.
agent:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| name | body | string | yes | Agent display name |
| description | body | string | no | Agent purpose description |
| riskTier | body | string | no | Initial risk tier: low, medium, high, critical |
| shadowMode | body | boolean | no | Start in shadow mode (log only, never block). Default: false |
{
"name": "code-assistant",
"description": "GitHub PR review agent",
"riskTier": "medium"
}{
"id": "agt_01HXYZ...",
"name": "code-assistant",
"agentKey": "sa_live_...",
"riskTier": "medium",
"shadowMode": false,
"createdAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/agentsList all agents in a tenant.
agent:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
/tenants/:tenantId/agents/:agentIdGet a single agent with full configuration.
agent:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| agentId | path | uuid | yes | Agent UUID |
/tenants/:tenantId/agents/:agentIdUpdate agent metadata (name, description, shadowMode, riskTier).
agent:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| agentId | path | uuid | yes | Agent UUID |
| name | body | string | no | Updated agent name |
| description | body | string | no | Updated description |
| shadowMode | body | boolean | no | Toggle shadow mode |
| riskTier | body | string | no | Updated risk tier |
/tenants/:tenantId/agents/:agentIdDeregister an agent and revoke its key.
agent:delete| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| agentId | path | uuid | yes | Agent UUID |
{ "deleted": true, "id": "agt_01HXYZ..." }/tenants/:tenantId/agents/:agentId/rotate-keyRotate the agent's API key. The old key is immediately revoked.
agent:write{
"agentKey": "sa_live_NEW...",
"rotatedAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/agents/:agentId/security-configConfigure per-agent security detection settings.
agent:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| injectionDetectionEnabled | body | boolean | no | Enable ML injection detection |
| dlpEnabled | body | boolean | no | Enable DLP scanning |
| excessiveAgencyEnabled | body | boolean | no | Enable excessive agency detection |
| toolDriftEnabled | body | boolean | no | Enable tool drift monitoring |
/tenants/:tenantId/agents/:agentId/baseline-configConfigure baseline learning parameters.
agent:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| warmupDays | body | integer | no | Days before drift detection activates (default: 7) |
| sensitivityMultiplier | body | number | no | Drift sensitivity (0.5–3.0, default: 1.0) |
/tenants/:tenantId/agents/:agentId/lockSuspend an agent. All tool calls will be blocked until unlocked.
agent:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| reason | body | string | no | Reason for suspension (written to audit trail) |
/tenants/:tenantId/agents/:agentId/unlockReinstate a suspended agent.
agent:write/tenants/:tenantId/agents/:agentId/baselineReset an agent's behavioral baseline. Drift scoring restarts from zero.
agent:write{ "reset": true, "agentId": "agt_01HXYZ..." }Policies
/tenants/:tenantId/policiesCreate a policy rule for a tenant, agent, or tool.
policy:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| agentId | body | uuid | no | Scope to a specific agent (omit for tenant-wide) |
| toolName | body | string | yes | Tool pattern to match (supports wildcards) |
| action | body | string | yes | allow, deny, or shadow |
| conditions | body | object | no | Optional condition object (method, path, param matchers) |
| priority | body | integer | no | Evaluation priority (lower = first). Default: 100. |
{
"agentId": "agt_01HXYZ...",
"toolName": "rest:stripe",
"action": "deny",
"conditions": { "method": "DELETE" }
}{
"id": "pol_01...",
"toolName": "rest:stripe",
"action": "deny",
"conditions": { "method": "DELETE" },
"createdAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/policiesList active policies for a tenant, optionally filtered by agent.
policy:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| agentId | query | uuid | no | Filter by agent |
/tenants/:tenantId/policies/:policyIdGet a single policy by ID.
policy:read/tenants/:tenantId/policies/:policyIdReplace a policy rule.
policy:write/tenants/:tenantId/policies/:policyIdPartially update a policy rule.
policy:write/tenants/:tenantId/policies/:policyIdDelete a policy rule.
policy:delete{ "deleted": true, "id": "pol_01..." }/tenants/:tenantId/policies/evaluateDry-run: evaluate policies against a hypothetical tool call without writing to audit trail.
policy:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| agentId | body | uuid | no | Agent UUID to evaluate against |
| toolName | body | string | yes | Tool name to test |
| params | body | object | no | Tool parameters |
{
"decision": "deny",
"matchedPolicy": { "id": "pol_01...", "toolName": "rest:stripe", "action": "deny" },
"reason": "Matched deny rule for DELETE on rest:stripe"
}/tenants/:tenantId/policies/templatesList available built-in policy templates.
policy:readPolicy Templates
/policy-templatesList all available built-in policy templates.
policy:read[
{
"id": "pii-protection",
"name": "PII Protection",
"description": "Block tool calls that expose PII fields",
"policyCount": 4
}
]/policy-templates/:templateIdGet a single template with all policy definitions.
policy:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| templateId | path | string | yes | Template slug (e.g. pii-protection) |
/tenants/:tenantId/policy-templates/:templateId/applyApply a template — creates all its policies in the tenant.
policy:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | uuid | yes | Tenant UUID |
| templateId | path | string | yes | Template slug |
| agentId | body | uuid | no | Scope policies to a specific agent (omit for tenant-wide) |
{
"templateName": "pii-protection",
"policiesCreated": 4,
"policyIds": ["pol_01...", "pol_02...", "pol_03...", "pol_04..."]
}/tenants/:tenantId/policy-templates/:templateId/removeRemove all policies that were applied from a template.
policy:delete{ "removed": 4, "templateName": "pii-protection" }/tenants/:tenantId/policy-templates/appliedList templates that have been applied to this tenant.
policy:readIncidents
/tenants/:tenantId/incidentsList incidents with filtering by status, severity, and agent.
incident:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | string | no | Filter: open, investigating, resolved |
| severity | query | string | no | Filter: low, medium, high, critical |
| agentId | query | uuid | no | Filter by agent |
| limit | query | integer | no | Max results (default 50, max 500) |
| offset | query | integer | no | Pagination offset |
/tenants/:tenantId/incidentsOpen a new incident manually.
incident:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| agentId | body | uuid | no | Related agent |
| title | body | string | yes | Incident title |
| severity | body | string | yes | low, medium, high, or critical |
| type | body | string | no | injection, drift, policy_violation, anomaly, or manual |
| data | body | object | no | Arbitrary incident context data |
{
"id": "inc_01...",
"title": "Prompt injection detected",
"severity": "critical",
"status": "open",
"createdAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/incidents/:incidentIdGet a single incident with full audit context.
incident:read/tenants/:tenantId/incidents/:incidentIdUpdate incident status or severity.
incident:triage| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| status | body | string | no | open, investigating, or resolved |
| severity | body | string | no | Updated severity |
| resolution | body | string | no | Resolution notes (required when status = resolved) |
/tenants/:tenantId/incidents/countGet incident counts grouped by status and severity.
incident:read{
"total": 42,
"byStatus": { "open": 12, "investigating": 5, "resolved": 25 },
"bySeverity": { "critical": 3, "high": 8, "medium": 18, "low": 13 }
}/tenants/:tenantId/incidents/:incidentId/auditList audit events linked to an incident.
incident:readAudit Trail
/tenants/:tenantId/auditList audit events with filtering, pagination, and optional Merkle proof.
audit:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| agentId | query | uuid | no | Filter by agent |
| tool | query | string | no | Filter by tool name |
| outcome | query | string | no | Filter: allow, block, shadow |
| from | query | ISO8601 | no | Start timestamp |
| to | query | ISO8601 | no | End timestamp |
| limit | query | integer | no | Max results (default 100, max 1000) |
| offset | query | integer | no | Pagination offset |
{
"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 }
}/tenants/:tenantId/audit/:eventIdGet a single audit event with full payload and Merkle proof.
audit:read/tenants/:tenantId/audit/verifyVerify the Merkle integrity of a batch of audit events.
audit:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| eventIds | body | uuid[] | yes | Array of event IDs to verify |
{
"verified": true,
"checkedCount": 50,
"tamperDetected": false
}/tenants/:tenantId/audit/exportStream audit events as NDJSON for bulk export.
audit:readResponse is streamed. Content-Type: application/x-ndjson. No pagination — returns all events in the window.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| from | query | ISO8601 | no | Start timestamp (required) |
| to | query | ISO8601 | no | End timestamp (required) |
| format | query | string | no | ndjson or json (default: ndjson) |
Risk Scoring
/tenants/:tenantId/risk/scoresGet current risk scores for all agents in a tenant.
risk:read{
"data": [
{
"agentId": "agt_01HXYZ...",
"agentName": "code-assistant",
"currentScore": 0.67,
"tier": "high",
"trend": "increasing",
"updatedAt": "2026-04-24T14:23:00Z"
}
]
}/tenants/:tenantId/risk/scores/:agentIdGet detailed risk score with component breakdown for a specific agent.
risk:read{
"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"
}/tenants/:tenantId/risk/scores/:agentId/historyGet risk score history for an agent (24h rolling window by default).
risk:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| window | query | string | no | Time window: 1h, 6h, 24h, 7d (default: 24h) |
/tenants/:tenantId/risk/scores/:agentId/recalculateForce an immediate risk score recalculation for an agent.
risk:write{
"agentId": "agt_01HXYZ...",
"previousScore": 0.67,
"newScore": 0.54,
"recalculatedAt": "2026-04-24T14:30:00Z"
}/tenants/:tenantId/risk/configGet risk enforcement configuration for the tenant.
risk:read{
"monitorThreshold": 0.30,
"blockThreshold": 0.80,
"autoLockThreshold": 0.95,
"humanReviewThreshold": 0.60
}/tenants/:tenantId/risk/configUpdate risk enforcement thresholds for the tenant.
risk:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| monitorThreshold | body | number | no | Score at which monitoring alerts trigger (0.0–1.0) |
| blockThreshold | body | number | no | Score at which auto-block activates (0.0–1.0) |
| autoLockThreshold | body | number | no | Score at which agent is suspended (0.0–1.0) |
| humanReviewThreshold | body | number | no | Score at which human review is required (0.0–1.0) |
/tenants/:tenantId/risk/baselines/:agentIdGet the behavioral baseline for an agent.
risk:read/tenants/:tenantId/risk/baselines/:agentIdReset an agent's behavioral baseline.
risk:write{ "reset": true, "agentId": "agt_01HXYZ..." }/tenants/:tenantId/risk/anomalies/analyzeRun an anomaly analysis on the last N hours of agent activity.
risk:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| agentId | body | uuid | no | Agent to analyze (omit for tenant-wide) |
| windowHours | body | integer | no | Lookback window (default: 24) |
{
"anomaliesDetected": true,
"results": [
{
"anomalyType": "tool_burst",
"anomalyScore": 0.91,
"explanation": "Agent called 47 tools in 60 seconds (4.2σ above baseline)"
}
]
}Compliance
/tenants/:tenantId/compliance/checklistGet the current compliance posture with gap analysis.
compliance:read{
"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"]
}
]
}/tenants/:tenantId/compliance/annex-iv/reportGenerate an Annex IV PDF report from the audit trail.
compliance:readResponse is streamed. Content-Type: application/pdf. The PDF is generated from the immutable audit trail with Merkle integrity proofs.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| periodStart | body | ISO8601 | yes | Report period start |
| periodEnd | body | ISO8601 | yes | Report period end |
| format | body | string | no | pdf or json (default: pdf) |
/tenants/:tenantId/compliance/reportsList previously generated compliance reports.
compliance:read/tenants/:tenantId/compliance/snapshotsGet compliance snapshots over time (for trending).
compliance:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | no | Max snapshots (default 30) |
/tenants/:tenantId/compliance/iso42001/gap-analysisISO 42001 gap analysis against the agent inventory.
compliance:read/tenants/:tenantId/compliance/nist-ai-rmf/gap-analysisNIST AI RMF gap analysis (Govern, Map, Measure, Manage functions).
compliance:read/tenants/:tenantId/compliance/regulatory-notificationsCreate a regulatory incident notification draft (EU AI Act Art. 73).
compliance:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| incidentId | body | uuid | yes | Related incident UUID |
| notificationDeadline | body | ISO8601 | no | Regulatory deadline (auto-calculated from incident date if omitted) |
Alerts
/tenants/:tenantId/alerts/rulesList alert rules.
alert:read/tenants/:tenantId/alerts/rulesCreate an alert rule.
alert:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| name | body | string | yes | Rule name |
| condition | body | string | yes | CEL condition expression (e.g. riskScore >= 0.70) |
| severity | body | string | yes | low, medium, high, or critical |
| channels | body | string[] | no | Delivery channels: webhook, email, slack |
| webhookUrl | body | string | no | Webhook delivery URL |
| agentId | body | uuid | no | Scope to a specific agent |
/tenants/:tenantId/alerts/rules/:ruleIdUpdate an alert rule.
alert:write/tenants/:tenantId/alerts/rules/:ruleIdDelete an alert rule.
alert:delete/tenants/:tenantId/alerts/eventsList fired alert events.
alert:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | no | Max results (default 100, max 500) |
| from | query | ISO8601 | no | Start timestamp |
MCP Servers
/tenants/:tenantId/mcp-serversRegister an MCP server for scanning and tool discovery.
mcp_server:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| name | body | string | yes | MCP server display name |
| url | body | string | yes | MCP server URL or stdio command |
| transport | body | string | no | http-sse or stdio (default: http-sse) |
| scanOnRegister | body | boolean | no | Run initial scan on registration (default: true) |
{
"id": "mcp_01...",
"name": "filesystem-server",
"url": "http://localhost:8080",
"transport": "http-sse",
"createdAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/mcp-serversList registered MCP servers.
mcp_server:read/tenants/:tenantId/mcp-servers/:mcpServerIdGet a single MCP server with tool inventory.
mcp_server:read/tenants/:tenantId/mcp-servers/:mcpServerIdUpdate MCP server configuration.
mcp_server:write/tenants/:tenantId/mcp-servers/:mcpServerIdDeregister an MCP server.
mcp_server:delete{ "deleted": true, "id": "mcp_01..." }/tenants/:tenantId/mcp-servers/:mcpServerId/refresh-toolsRe-discover tools from the MCP server.
mcp_server:write{
"toolsDiscovered": 12,
"toolsAdded": 2,
"toolsRemoved": 0,
"refreshedAt": "2026-04-24T12:00:00.000Z"
}/tenants/:tenantId/mcp-servers/:mcpServerId/scanRun a security scan on the MCP server's tools.
mcp_server:write{
"scanId": "scan_01...",
"status": "completed",
"vulnerabilities": 1,
"toolCount": 5,
"scanDuration": 1240
}/tenants/:tenantId/mcp-servers/:mcpServerId/scansGet scan history for an MCP server.
mcp_server:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | no | Max results (default 20, max 100) |
/tenants/:tenantId/scansTenant-wide scan history across all MCP servers.
mcp_server:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| limit | query | integer | no | Max results (default 50, max 200) |
Reviews
Human-in-the-loop review queue for tool calls that require approval before execution.
/tenants/:tenantId/reviewsList pending reviews with filtering and pagination.
review:read| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| status | query | string | no | Filter: pending, approved, denied |
| agentId | query | uuid | no | Filter by agent |
| limit | query | integer | no | Max results (default 50, max 500) |
| offset | query | integer | no | Pagination offset |
/tenants/:tenantId/reviews/countGet review counts by status.
review:read{ "pending": 5, "approved": 120, "denied": 8 }/tenants/:tenantId/reviews/:reviewIdGet a single review with agent name.
review:read/tenants/:tenantId/reviews/:reviewId/decideApprove or deny a pending review.
review:triage| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| decision | body | string | yes | approved or denied |
| comment | body | string | no | Optional reviewer comment |
{
"decision": "approved",
"comment": "Verified safe — one-time file access needed"
}Notifications
/tenants/:tenantId/notificationsList in-app notifications for the current user.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| unreadOnly | query | boolean | no | Filter to unread only |
| limit | query | integer | no | Max results (default 50, max 200) |
/tenants/:tenantId/notifications/:id/readMark a single notification as read.
/tenants/:tenantId/notifications/read-allMark all unread notifications as read.
{ "marked": 12 }Passports
Agent Passports provide verifiable identity cards for AI agents. Requires Business tier or above.
/tenants/:tenantId/agents/:agentId/passportGet an agent's passport with risk assessment, compliance status, and signature.
passport:readRequires agent_passport feature entitlement (Business+ plan).
/tenants/:tenantId/agents/:agentId/passportUpdate passport display metadata.
passport:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| displayName | body | string | no | Public display name |
| description | body | string | no | Public description |
| avatarUrl | body | string | no | Avatar image URL (SSRF-protected) |
| visibility | body | string | no | private, internal, or public |
/tenants/:tenantId/agents/:agentId/passport/refreshRecompute and re-sign the passport with latest data.
passport:write/tenants/:tenantId/agents/:agentId/passport/publishPublish the passport for external verification.
passport:writePublishing as public requires elevated role (security_manager, tenant_admin, or platform_admin).
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| visibility | body | string | no | public or internal (default: internal) |
/tenants/:tenantId/agents/:agentId/passport/unpublishUnpublish a passport — sets visibility to private.
passport:write/public/passports/:tenantSlug/:agentSlugView a published passport (public, unauthenticated).
Rate-limited to 60 requests/minute per IP. Returns cached response (max-age 300s).
/public/passports/:tenantSlug/:agentSlug/verifyVerify a passport's cryptographic signature (public, unauthenticated).
{
"verified": true,
"valid": true,
"passportHash": "sha256:abc123...",
"signature": "base64:...",
"signedAt": "2026-04-24T12:00:00.000Z",
"keyId": "key_01...",
"publicKey": "-----BEGIN PUBLIC KEY-----..."
}/public/passports/:tenantSlug/:agentSlug/badge.svgRender an embeddable SVG badge for the agent (public, unauthenticated).
Rate-limited to 300 requests/minute per IP. Content-Type: image/svg+xml.
Billing
/billing/statusCurrent plan tier and subscription status.
tenant:read{
"planTier": "pro",
"billingState": "active",
"hasStripeCustomer": true,
"hasSubscription": true
}/billing/entitlementsFeature entitlements and limits for the current plan.
tenant:read{
"planTier": "pro",
"billingState": "active",
"entitlements": {
"maxAgents": 50,
"includedToolCalls": 100000,
"retentionDays": 365,
"features": ["agent_passport", "sso", "custom_policies"]
}
}/billing/usageCurrent month usage and plan limits.
tenant:read{
"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
}/billing/checkoutCreate a Stripe Checkout session for plan upgrade.
tenant:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tier | body | string | yes | Target plan: free, team, starter, pro, business |
| successPath | body | string | no | Redirect path after success |
| cancelPath | body | string | no | Redirect path on cancel |
{ "checkoutUrl": "https://checkout.stripe.com/c/pay_..." }/billing/portalCreate a Stripe Customer Portal session for subscription management.
tenant:write{ "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.
/tenants/:tenantId/export-configsCreate an export configuration.
export:write| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| name | body | string | yes | Config display name |
| destinationType | body | string | yes | s3, webhook, or syslog |
| config | body | object | yes | Destination-specific config (bucket, url, host, etc.) |
| credentials | body | object | no | Auth credentials (encrypted at rest, never returned) |
| filters | body | object | no | Event filters (agent, tool, outcome, etc.) |
| intervalSeconds | body | integer | no | Export interval (30–86400 seconds) |
| format | body | string | no | ndjson or json (default: ndjson) |
| enabled | body | boolean | no | Active on creation (default: true) |
{
"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"
}/tenants/:tenantId/export-configsList export configs (credentials redacted).
export:read/tenants/:tenantId/export-configs/:configIdUpdate an export config (partial update, credentials redacted in response).
export:write/tenants/:tenantId/export-configs/:configIdDelete an export configuration.
export:delete/tenants/:tenantId/export-configs/:configId/testTest the export adapter connection.
export:write{ "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
/tenants/:tenantId/scanSubmit 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 <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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | string (uuid) | yes | Your tenant UUID |
| agentId | body | string (uuid) | no | ShieldAgent 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. |
| clientHint | body | string | no | MCP 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. |
| toolName | body | string | yes | Name of the tool being called (e.g. "read_file", "api:POST:/payments") |
| params | body | object | yes | Tool call parameters as a JSON object |
| include_findings | body | boolean | no | Request 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.transport | body | "mcp" | "rest" | "custom" | no | Transport protocol between agent and your server |
| context.sourceIp | body | string | no | IP address of the agent. Used for per-IP rate limiting. |
| context.sessionId | body | string | no | Session identifier. Used for excessive agency detection across calls in the same session. |
{
"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"
}
}{
"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.
{
"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
When to omit agentId
| Scenario | agentId | Pipeline behaviour |
|---|---|---|
| MCP server (typical) | omit | Tenant-level policies only. Optionally pass clientHint from the MCP clientInfo.name handshake. |
| HTTP API with agent auth mapping | provide | Full per-agent pipeline: policies, risk score, rate limits, baseline, approved tools. |
| HTTP API without agent mapping | omit | Tenant-level policies only. Rate limiting applies per-tenant. |
/tenants/:tenantId/verdict-confirmationsReport 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.
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.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| tenantId | path | string (uuid) | yes | Your tenant UUID |
| auditEventId | body | string (uuid) | yes | The auditEventId returned by POST /scan |
| executed | body | boolean | yes | true 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) |
{
"auditEventId": "evt-a1b2c3d4-0000-0000-0000-000000000001",
"executed": false
}{ "recorded": true }Health
/healthzLiveness probe. Returns service status and timestamp.
Excluded from rate limiting. Use for Kubernetes liveness/readiness probes.
{
"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.
# Serve Swagger UI locally
npx @redocly/cli preview-docs docs/openapi/shieldagent-api.yaml