Console & fleet

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.

~7 min read · Console & fleet

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.
It is the programmatic counterpart to the console panel: the same lifecycle, driven from CI/CD, Ansible, an SSH loop, or an MDM such as SCCM or Intune.

Management plane versus data plane

The decisive property is what this API does not see. The system has two distinct planes:

PlaneTrafficSees content?
Management planeThis 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 planeThe 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.
Audit reporting and decision feedback are daemon data-plane traffic, not management-plane calls. Provisioning a thousand machines through the API exposes no protected content to it.

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.

bashTerminal
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:

EndpointPurposeReturns
POST /v1/appsCreate an app and a first enrollment code in one call (optional body {"name":"..."}).201 with appId, enrollCode, enrollCodeExpiresAt.
GET /v1/appsList 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-codeMint 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}/revokeDeactivate 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-configManage 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:

FieldMeaning
appIdStable app identifier.
nameDisplay name.
statuspending, active or revoked.
platformReported operating system.
agentVersionReported daemon version.
lastSeenAt, createdAtTimestamps.

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:

StatusMeaning
400Validation, for example invalid_name or limit_reached.
401Missing, invalid or revoked key, or a disabled account.
404Unknown endpoint, or an unknown or foreign app ID.
413Request body over 64 KiB (payload_too_large).
429Too many requests; slow down and retry (up to 600 per minute per account).
Policy profiles, watched paths and thresholds are configured in the console panel, not through this API; the REST surface covers the app lifecycle and the OpenTelemetry export configuration. The machine-readable OpenAPI 3 specification is published at /docs/api/openapi.json.

The Enterprise export configured through /v1/otel-config: OpenTelemetry export. Where enrollment codes are used at rollout: installing PoisonZero.

Was this helpful?

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