← Help

API Guide

Pro-only read-only programmatic access to your organization's domains and findings.

1. Get a key

API keys are a Pro feature. Create one from your organization's API Keys page (in the sidebar, owners and admins only). The full key is shown exactly once, immediately after creation, in a copy-to-clipboard box. If you lose it, there's no way to retrieve it again. Revoke it and create a new one.

Treat it like a password: anyone with the key can read every domain and finding in that organization until it's revoked. Don't commit it to a repository or paste it somewhere public.

2. Authenticate

Send it as a bearer token on every request:

curl https://cyberenforced.io/api/v1/domains \
  -H "Authorization: Bearer cek_..."

A missing, malformed, or revoked key gets a 401. A valid key on a Free organization gets a 403:

{ "error": "unauthorized" }
{ "error": "API access requires Pro" }

3. Endpoints

GET /api/v1/domains

Every domain in the key's organization, including subdomains automatically discovered and scanned under a domain you added (auto_discovered: true, with parent_domain_id pointing back to it).

{
  "domains": [
    {
      "id": "3a1e...",
      "domain": "example.com",
      "verification_status": "unverified",
      "last_scan_at": "2026-09-10T04:00:00.000Z",
      "created_at": "2026-08-01T12:00:00.000Z",
      "parent_domain_id": null,
      "auto_discovered": false
    },
    {
      "id": "9c2f...",
      "domain": "portal.example.com",
      "verification_status": "verified",
      "last_scan_at": "2026-09-10T04:05:00.000Z",
      "created_at": "2026-09-10T04:00:00.000Z",
      "parent_domain_id": "3a1e...",
      "auto_discovered": true
    }
  ]
}

GET /api/v1/findings

Every finding across every domain in the organization, newest first. Two optional query parameters narrow it down:

ParameterValues
statusopen, acknowledged, resolved
severitycritical, high, medium, low, info
curl "https://cyberenforced.io/api/v1/findings?status=open&severity=critical" \
  -H "Authorization: Bearer cek_..."
{
  "findings": [
    {
      "id": "7bf8...",
      "category": "invalid_tls",
      "severity": "critical",
      "title": "Invalid or expired TLS certificate",
      "detail": "The TLS certificate presented on port 443 is missing, expired, or failed validation.",
      "status": "open",
      "due_date": null,
      "domain": "example.com"
    }
  ]
}

An invalid status or severity value gets a 400 with a message listing the valid ones, rather than silently ignoring the filter.

4. What to expect (and what not to)

  • Read-only. There is no way to create, update, or delete anything through this API yet. No endpoint for adding a domain, changing a finding's status, inviting a member, etc.
  • No pagination yet. Both endpoints return everything that matches in a single response. For most organizations that's a small, fast payload; if yours has an unusually large number of domains or findings, expect a correspondingly larger response rather than pages.
  • No rate limiting is enforced today. Please still be reasonable: poll on the order of minutes, not requests-per-second, since this may change to an enforced limit in the future without much notice.
  • No uptime SLA. This API runs on the same infrastructure as the rest of the app, with no separate availability guarantee.
  • /v1/ is a real version marker. A breaking change to response shapes or behavior will go to a new /v2/ path rather than changing /v1/ underneath you.
  • Scoped to one organization. A key only ever sees the organization it was created in. There's no way to query across organizations with a single key, even if you belong to more than one.

5. Revoking a key

Click Revoke next to it on the API Keys page. This takes effect immediately. The very next request with that key returns 401. Revoking is permanent; the row is kept (so you can still see when it was created and last used) but it can't be un-revoked.

API Guide | CyberEnforced