Skip to content
devtls

API reference

The dashboard is built on this API, so anything it does, your scripts can do. The base URL is https://devtls.fleeq.net/api. Requests and responses are JSON.

Send an API key as a bearer token:

Terminal window
curl -H "authorization: Bearer dtls_…" https://devtls.fleeq.net/api/domains

A key acts for the organization it was created in. Keys need a paid plan; only owners and admins can create them. Team management and billing are only available to a signed-in user, not to a key.

GET /domains — optionally ?kind=web or ?kind=mail.

{
"domains": [
{
"id": 42,
"host": "example.com",
"port": 443,
"label": "prod",
"kind": "web",
"latest": { "id": 913, "status": "success", "grade": "A", "score": 90, "createdAt": "…" },
"active": null,
"expiryDays": 61,
"scores": [88, 88, 90]
}
]
}

latest is the most recent finished scan, active a scan still queued or running.

POST /domains

Field Type
host string required; a URL is accepted and reduced to its host
port number web targets; default 443
kind "web" | "mail" default "web"
label string optional
mailPorts number[] mail targets; any of 25, 110, 143, 465, 587, 993, 995; default 587, 465, 993, 995
dkimSelectors string[] mail targets; selectors to check besides the common ones

Answers 201 { "domain": {…} }, or 409 with code: "DUPLICATE" and the existing domain.

GET /domains/{id} — the domain (with its badgeToken), its scan history in scans, the full latest scan and any active one.

DELETE /domains/{id} — 204. Its scans are deleted with it.

POST /domains/{id}/scan

Query
deep=1 also fetch the SSL Labs grade (paid plans)
ciphers=1 enumerate every accepted cipher suite per TLS version ≤ 1.2

Answers 202 { "scan": {…} } with the queued scan.

GET /scans/{id}

{
"scan": {
"id": 913,
"createdAt": "2026-10-13 07:00:03",
"status": "success",
"reachable": true,
"grade": "A",
"score": 90,
"summary": "Strong TLS configuration …",
"error": null,
"result": { "protocols": { … }, "cipher": { … }, "certificate": { … }, "hsts": { … }, "addresses": [ … ], "fixes": [ … ] }
}
}

status is queued, running, success or failed. result holds everything the report shows: per-protocol results, the cipher, certificate details, HSTS, one entry per resolved address, the fixes, and — after a deep scan — externalGrades.

POST /mail-dns-check with { "domain": "example.com", "dkimSelectors": ["s1"] } checks SPF, DKIM, DMARC, MTA-STS and TLS-RPT immediately, without storing anything:

{ "dns": { … }, "findings": [ … ], "score": 85 }
GET /config-checks your organization’s reviews
POST /config-checks review pasted text: { "content": "…", "kind": "nginx" } — kind is optional and one of docker-compose, traefik-dynamic, traefik-static, nginx, caddy
GET /config-checks/{id} one review with its findings
DELETE /config-checks/{id} delete it

GET /plans is public: every plan with its prices (in cents) and limits. It’s what Plans is made from.

Errors are { "error": "message" }, plus a code where a client can act on it.

Status code Meaning
400 — invalid input, or a target that resolves to a private address
401 — missing or invalid key or session
403 PLAN_LIMIT the plan’s domain limit, or the month’s config reviews, are used up
403 SCAN_LIMIT the month’s scans are used up (resets on the 1st, UTC)
403 FEATURE_LOCKED the plan doesn’t include this (deep scans, webhooks, metrics, API keys)
403 BAD_ORIGIN a browser request from another site, blocked
404 — no such domain or scan in this organization
409 DUPLICATE the domain already exists
429 — too many scans, DNS checks or config reviews; wait for Retry-After seconds
  • About 10 scans a minute per organization, with similar limits on mail DNS checks and config reviews.
  • Scans and config reviews per month, and domains in total, as in Plans.