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:
| Parameter | Values |
|---|---|
status | open, acknowledged, resolved |
severity | critical, 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.