본문으로 건너뛰기
이 페이지는 아직 사용자의 언어로 번역되지 않았거나 번역이 기술 검토를 기다리고 있습니다. 아래에는 영어 원문이 표시됩니다. 영어 페이지 열기

API Reference

The Control Zero backend exposes three families of HTTP endpoints:

  1. SDK endpoints (/v1/sdk/*) — called by Control Zero SDKs. Authenticated with a project API key (cz_live_* or cz_test_*).
  2. Public API (/v1/*) — thin, stable surface for programmatic org-level policy management. Authenticated with a project API key.
  3. Dashboard API (/api/*) — powers the Control Zero dashboard. Authenticated with a first-party cz_session cookie (SaaS) or a database-backed JWT session (self-managed). SDK users do not call these directly.

Use the SDK for normal application code. The direct API is useful for custom tooling, CI/CD, and platform integrations.

Base URL​

https://api.controlzero.ai

All endpoints are served from this host. There is no /v1 prefix on the base URL itself — individual routes specify their own prefix (/v1/sdk/..., /v1/policies/..., /api/...).

For self-managed deployments, replace the host with your own backend URL.

Authentication​

Project API key (SDK + public API)​

Endpoints under /v1/sdk/*, /v1/policies*, and /api/scout/* accept a project API key. Keys start with cz_live_ (production) or cz_test_ (test/development).

Two header forms are accepted, either works:

# Preferred
curl -H "X-API-Key: cz_live_..." \
https://api.controlzero.ai/v1/sdk/bootstrap

# Also accepted
curl -H "Authorization: Bearer cz_live_..." \
https://api.controlzero.ai/v1/sdk/bootstrap

A request missing a valid API key returns 401 MISSING_API_KEY. A key that does not start with cz_live_ or cz_test_ returns 401 INVALID_API_KEY_FORMAT. An unknown key returns 401 INVALID_API_KEY.

Gateway uses a different header name

The backend at api.controlzero.ai accepts X-API-Key or Authorization: Bearer. The hosted gateway at gateway.controlzero.ai accepts X-ControlZero-API-Key or Authorization: Bearer instead (to avoid colliding with the upstream provider's X-Api-Key header, e.g. Anthropic). If you are calling the gateway directly, use X-ControlZero-API-Key. If you are calling the backend, use X-API-Key.

Scopes​

API keys carry scopes (read, write, scout). SDK endpoints require at least read. Mutating public-API endpoints require write. Scout endpoints require scout. A key without the required scope returns 403 INSUFFICIENT_SCOPE.

Dashboard auth (/api/*)​

Dashboard endpoints authenticate with a first-party cz_session cookie (SaaS mode) or a JWT session token (self-managed mode). On SaaS, sign-in (email + password or Google) is handled by Control Zero's self-hosted identity service; the frontend then exchanges the identity session for the cz_session cookie. These endpoints are intended for the Control Zero dashboard frontend. SDK users should not call them directly; there is no stable public contract.

Event stream query param​

The SSE stream at /api/events/stream also accepts an access_token query parameter, because browsers cannot set custom headers on EventSource. This is the only endpoint that accepts a key via query string.

Request format​

  • Request bodies must be JSON with Content-Type: application/json.
  • Request bodies are capped at 1 MB. Oversized requests return 413 Request Entity Too Large.
  • Responses are JSON unless otherwise noted (policy bundles are binary application/octet-stream).
  • Timestamps are ISO 8601 in UTC.

HTTP status codes​

CodeMeaning
200Success
201Created
204No content (successful delete)
304Not modified (ETag matched)
400Bad request
401Missing or invalid authentication
403Authenticated but missing scope / role
404Resource not found
413Request body too large
429Rate limit exceeded
500Server error
503Feature disabled or dependency unavailable

Error format​

{
"error": {
"code": "INVALID_API_KEY",
"message": "invalid API key"
}
}

Rate limiting​

Every authenticated path runs behind a combined IP + API-key rate limiter:

  • 1000 requests / minute per source IP (DDoS guard)
  • 500 requests / minute per API key (tenant abuse guard)

When the limit is exceeded, the server returns 429 Too Many Requests. Clients should back off with exponential retry. Rate limit state is keyed in an in-memory cache; limits are shared across backend instances.

SDK endpoints (/v1/sdk/*)​

All SDK endpoints require a project API key with read scope (plus any per-endpoint scope noted below). They are what the Python and Node SDKs call under the hood.

POST /v1/sdk/init​

Declares the SDK session on startup. Used for session tracking and usage metering.

curl -X POST https://api.controlzero.ai/v1/sdk/init \
-H "X-API-Key: cz_live_..." \
-H "Content-Type: application/json" \
-d '{"sdk_version": "1.13.8", "agent_name": "agent-001"}'

POST /v1/sdk/logs​

Submits a batch of local audit log entries for ingest into the governance audit trail. Used by SDKs in hybrid mode.

curl -X POST https://api.controlzero.ai/v1/sdk/logs \
-H "X-API-Key: cz_live_..." \
-H "Content-Type: application/json" \
-d '{"logs": [ { "tool_name": "llm", "method_name": "generate", "policy_decision": "allow", "timestamp": "2026-04-15T12:00:00Z" } ]}'

POST /v1/sdk/refresh​

Refreshes the SDK session handle.

GET /v1/sdk/bootstrap​

Returns the hosted-mode bootstrap payload: the org's signing public key and the project's encryption key material needed to verify and decrypt a signed policy bundle.

curl -H "X-API-Key: cz_live_..." \
https://api.controlzero.ai/v1/sdk/bootstrap

Response (200):

{
"project_id": "proj_...",
"org_id": "org_...",
"project_encryption_key_b64": "<base64-encoded AES key>",
"signing_pubkey_hex": "<hex-encoded public key>",
"signing_pubkey_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
"key_version": 1,
"algorithm": "signature-v1"
}

GET /v1/sdk/policies/pull​

Returns the signed + encrypted policy bundle for the caller's project. Supports ETag-based conditional requests: pass If-None-Match with the last seen ETag and receive 304 Not Modified when the bundle is unchanged.

Response content type is application/octet-stream. The body is a binary .czpolicy blob; the SDK verifies the signature and decrypts it in-process.

curl -H "X-API-Key: cz_live_..." \
-H "If-None-Match: \"v17\"" \
https://api.controlzero.ai/v1/sdk/policies/pull \
--output policy.czpolicy

GET /v1/sdk/keys/public​

Returns the org's verification public key used to verify policy bundle signatures. Typically called once during SDK bootstrap and cached.

POST /v1/sdk/audit​

Hosted-mode audit ingest. Accepts decision records from the SDK and writes them to the audit trail.

POST /v1/sdk/tamper-alert​

Reports a tamper detection event (signature verification failure, bundle decryption failure, or quarantine trigger). The backend records the alert and may escalate per the org's tamper_behavior setting.

Request body:

{
"agent_id": "agent-abc",
"severity": "critical",
"expected_checksum": "sha256:...",
"actual_checksum": "sha256:...",
"file_path": "/path/to/.czpolicy",
"source": "claude_code",
"hostname": "host-01",
"machine_id": "machine-abc",
"system_info": { "os": "linux" },
"details": { "reason": "signature_invalid" }
}

Public API (/v1/*)​

The public API currently exposes one resource: policies. Reads are stable surface area intended for CI/CD and custom tooling. The write routes have been retired -- see below.

GET /v1/policies​

List policies across the caller's org. Requires read scope.

curl -H "X-API-Key: cz_live_..." https://api.controlzero.ai/v1/policies

Response (200):

{
"policies": [
{
"id": "policy_...",
"name": "model-governance",
"version": 3,
"org_id": "org_...",
"project_id": "proj_...",
"updated_at": "2026-04-01T09:00:00Z"
}
]
}

POST /v1/policies, PATCH /v1/policies/{policyID}, DELETE /v1/policies/{policyID} — retired​

These three routes return 410 Gone and no longer write anything. Reading policies with GET /v1/policies is unaffected.

They were retired because an enforcement key (cz_live_ / cz_test_) carries the write scope, and write alone was enough to edit the policy that governs the agent holding that key. An SDK key sitting in an agent's environment could rewrite its own governing policy.

Authoring policies now requires a management key (cz_mgmt_), which is a separate credential kind with its own scopes:

Instead ofUse
POST /v1/policies with an enforcement keyPOST /v1/policies with a management key (policy:write)
PATCH /v1/policies/{policyID}POST /v1/policies/{policyID}/versions — an edit is a new version, not an in-place mutation
DELETE /v1/policies/{policyID}DELETE /v1/projects/{projectID}/attachments — detach the policy from the project

A management key is minted by an org admin in the dashboard under Settings → API keys. It is deliberately not issuable by an existing enforcement key, so this step needs a person once; automation cannot mint one for itself.

The 410 response body carries a machine-readable _deprecation object naming the replacement for the verb you called. If you want to check whether your automation was affected, filter your audit log for the action legacy_policy_write_refused.

Scout API (/api/scout/*)​

The Shadow AI Scout discovery agent uses this endpoint family. Requires an API key with scout scope.

MethodPathPurpose
POST/api/scout/registerRegister a Scout agent instance
POST/api/scout/heartbeatLiveness ping
POST/api/scout/discoveriesSubmit discovered AI surface records
GET/api/scout/configPull Scout configuration
POST/api/scout/license/validateValidate an on-prem Scout license

Machine-signed SDK endpoints (enrollment mode)​

When the SDK is enrolled against the backend with a signing keypair (rather than an API key), it calls these endpoints. Each request carries a per-request cryptographic signature verified by the MachineAuth middleware. No bearer token travels on the wire.

MethodPathPurpose
POST/api/enrollOne-time enrollment (no auth; token + pubkey)
POST/api/heartbeatMachine liveness
GET/api/policyPull policy bundle (machine-signed)
POST/api/auditSubmit audit events (machine-signed)

Enrollment is gated behind the ENROLLMENT_API_ENABLED flag; when disabled these routes return 503 FEATURE_DISABLED.

Dashboard API (/api/*)​

The dashboard endpoints are documented here for reference only. They authenticate with a first-party cz_session cookie (SaaS) or a database-backed JWT session (self-managed). SDK users should not rely on these; their URLs and payloads may change without notice.

The canonical resource path layout is:

/api/orgs/{orgID}
/api/orgs/{orgID}/members
/api/orgs/{orgID}/projects
/api/orgs/{orgID}/policies # all policies across projects
/api/orgs/{orgID}/settings
/api/orgs/{orgID}/dlp/rules
/api/orgs/{orgID}/sso
/api/orgs/{orgID}/enrollment-tokens
/api/orgs/{orgID}/fleet
/api/orgs/{orgID}/coverage
/api/orgs/{orgID}/notifications
/api/orgs/{orgID}/browser-extension
/api/orgs/{orgID}/compliance/browser-ext-ack

/api/projects/{projectID}
/api/projects/{projectID}/api-keys
/api/projects/{projectID}/tools
/api/projects/{projectID}/secrets
/api/projects/{projectID}/policies
/api/projects/{projectID}/keys # key provisioning / rotation
/api/projects/{projectID}/tamper-alerts
/api/projects/{projectID}/logs # audit log query
/api/projects/{projectID}/analytics
/api/projects/{projectID}/anomalies
/api/projects/{projectID}/compliance
/api/projects/{projectID}/mcp # hosted MCP provisioning (hosted MCP is COMING SOON; tracking: TODO-HOSTEDMCP-1287)
/api/projects/{projectID}/scout

Dashboard write operations require a CSRF token from GET /api/csrf-token in addition to the bearer auth header. This is not relevant to SDK callers.

A separate admin tree lives at /api/admin/* and requires an additional admin role check.

Live event stream (SSE)​

GET /api/events/stream

Server-Sent Events stream of governance decisions. Accepts the project API key as X-API-Key, Authorization: Bearer, or (only here) ?access_token= query param. Each event is a JSON object:

{
"id": "...",
"type": "decision",
"agent": "...",
"tool": "...",
"policy": "...",
"latency_ms": 12,
"timestamp": "..."
}
const es = new EventSource(
`https://api.controlzero.ai/api/events/stream?access_token=${encodeURIComponent(CZ_API_KEY)}`
);
Security trade-off

Query-string tokens can leak through browser history, referrer headers, and reverse-proxy access logs. Query-param auth is scoped to this one route. Anywhere else, use the X-API-Key or Authorization header.

SSO / SCIM / SAML​

Enterprise SSO endpoints live at /scim/v2/* (SCIM 2.0 user provisioning, bearer token auth) and /saml/{orgID}/* (SAML 2.0 SP). These are Teams-tier features, configured per-org via /api/orgs/{orgID}/sso. See the SSO setup guide for details.

Health​

MethodPathPurpose
GET/Root info
GET/healthLiveness probe
GET/readyReadiness probe (cache + secrets + auth check)

These are unauthenticated.

SDKs​

For most use cases, use an official SDK instead of calling the API directly:

The SDKs handle authentication, ETag-based bundle caching, signature verification, local decryption, audit batching, and retry/backoff.