Documentation

API & webhooks

Machine access to the same data the panel shows, and push delivery for new incidents.

Authentication

Create a key under Settings → API keys (Business and above). The plaintext value is shown once. Send it as a bearer token:

curl -H "Authorization: Bearer zi_live_..." \
  https://api.zoneinsight.example/v1/zones

A key is scoped to the organization that created it. Browser sessions use a cookie instead; both reach the same endpoints.

Reading data

EndpointReturns
GET /v1/zonesProtected domains
GET /v1/zones/{id}/stateInterpreted current state; ?at= for historical
GET /v1/zones/{id}/assetsThe zone's asset graph as a flat list
GET /v1/incidentsIncidents across every zone
GET /v1/eventsChange events across every zone
GET /v1/zones/{id}/evidenceEvidence availability and checkpoint detail

Incident webhooks

On Pro and above, set a URL under Settings → Alert webhook. Every newly opened incident is delivered as a JSON POST. The signing secret is shown once at set or rotate time.

POST /your-endpoint
X-ZoneInsight-Signature: sha256=<hex hmac of the raw body>
X-ZoneInsight-Timestamp: 1730000000
Content-Type: application/json

{
  "incident_id": 4213,
  "zone": "example.com",
  "rule": "possible_domain_takeover",
  "severity": "high",
  "confidence": "medium",
  "opened_at": "2026-08-31T14:02:11Z",
  "explanation": ["Nameservers changed", "DNSSEC DS removed"]
}

Verify by recomputing an HMAC-SHA256 of the raw request body with your secret and comparing in constant time. Reject timestamps outside a few minutes to blunt replay. Respond 2xx quickly; retries are attempted with backoff.

Errors and limits

Errors are { "error": { "code": "...", "message": "..." } } with a matching HTTP status. Plan limits are enforced server-side — a request over your domain limit returns 403 zone_limit_reached naming the plan. See pricing for the per-tier numbers.