The management API
Everything you can do per app in the console panel also works as a REST call, so a fleet can be provisioned from CI/CD, configuration management or an MDM. This page is the endpoint reference: what each call does, how you authenticate, and why the API never sees protected content.
What it is
- A small REST surface for the app lifecycle: create, enroll, list, deactivate and delete protected apps.
- Built for automation: bake an un-enrolled daemon into a golden image and mint enrollment codes in advance; each machine enrolls itself on first start.
- Machine-readable: an OpenAPI 3 specification is published alongside this page.
Management plane versus data plane
The decisive property is what this API does not see. The system has two distinct planes:
| Plane | Traffic | Sees content? |
|---|---|---|
| Management plane | This API: app lifecycle and metadata only (identifier, name, status, platform, agent version, timestamps, enrollment codes). | No: no memory content, no diff, no evaluation payload ever crosses it. |
| Data plane | The daemon's own traffic: check-ins and, in the cloud-assisted flow, evaluation of redacted diffs. | Content stays on the device; only a redacted projection is evaluated. |
Authentication
Callers authenticate with a bearer key created in the panel under Settings, API keys. The key (pz_live_ followed by forty characters) is shown once; at rest only its SHA-256 hash is stored, so a database disclosure yields no usable credential.
curl -H "Authorization: Bearer pz_live_..." \ https://poisonzero.com/api/v1/apps
- Owner-scoped: every request is bound to the key's owner.
- No enumeration: a foreign or unknown app answers an identical
404, so identifiers outside your fleet cannot be probed. - Ten active keys per account; any key can be revoked independently.
Endpoints
The endpoints mirror the panel and are reached over HTTPS at poisonzero.com/api/v1/. Every call takes the bearer key:
| Endpoint | Purpose | Returns |
|---|---|---|
POST /v1/apps | Create an app and a first enrollment code in one call (optional body {"name":"..."}). | 201 with appId, enrollCode, enrollCodeExpiresAt. |
GET /v1/apps | List your fleet. | One entry per app (see the app object below). |
GET /v1/apps/{appId} | Fetch one app. | 404 for unknown or foreign IDs. |
POST /v1/apps/{appId}/enroll-code | Mint a fresh enrollment code, for example to re-provision a machine. | 201; codes are single-use and valid for 30 days. |
POST /v1/apps/{appId}/revoke | Deactivate an app; status becomes revoked and the daemon's credentials stop working immediately. | appId and status. |
DELETE /v1/apps/{appId} | Delete an app permanently (app, configuration, daemon identity, open codes, review-queue entries; audit logs are retained). | 204. |
GET / PUT / DELETE /v1/otel-config | Manage the OpenTelemetry export configuration for the fleet (Enterprise). | See the observability export page. |
GET and PUT on /v1/otel-config require an Enterprise owner (otherwise 403); DELETE is always allowed so a downgraded owner can still purge a stored collector secret. The export itself: OpenTelemetry export.The app object
List and fetch return the lifecycle metadata of each app, never content:
| Field | Meaning |
|---|---|
appId | Stable app identifier. |
name | Display name. |
status | pending, active or revoked. |
platform | Reported operating system. |
agentVersion | Reported daemon version. |
lastSeenAt, createdAt | Timestamps. |
Transport
- HTTPS at
poisonzero.com/api/v1/; a reverse proxy forwards only the method, path, authorization header, content type and a size-capped body. - The path is decoded to a fixed point and any dot-segment or backslash is rejected, closing path-traversal attempts.
- Fleet management is not gated on an active subscription, so you can provision and revoke while a plan is being arranged.
Errors
All errors share one shape, {"error":{"code":"...","message":"..."}}, with a stable machine-readable code:
| Status | Meaning |
|---|---|
400 | Validation, for example invalid_name or limit_reached. |
401 | Missing, invalid or revoked key, or a disabled account. |
404 | Unknown endpoint, or an unknown or foreign app ID. |
413 | Request body over 64 KiB (payload_too_large). |
429 | Too many requests; slow down and retry (up to 600 per minute per account). |
/docs/api/openapi.json.Read next
The Enterprise export configured through /v1/otel-config: OpenTelemetry export. Where enrollment codes are used at rollout: installing PoisonZero.
Provision your whole fleet from a script.
Create, enroll and revoke over REST, with one static API key. The API never sees protected content.
Sign me up