Developers
The Hardn REST API. Scan from CI.
Register sites, prove ownership, start scans and read findings as JSON. The same ownership rules and credits as the app.
Your first scan is free, no card needed. You prove you own the site before Hardn touches it.
Authentication
Create a key in the app under API keys (owners and admins). Send it as a bearer token. Keys start with hk_live_, belong to one organisation, and are shown only once.
Authorization: Bearer hk_live_…| Base URL | https://api.hardn.si/v1 |
|---|---|
| Site ids | tgt_… |
| Scan ids | asm_… |
| Times | ISO-8601, UTC |
Quick start
Four calls from a new site to its report.
1. Register your site
bash curl -s https://api.hardn.si/v1/targets \ -H "Authorization: Bearer $HARDN_KEY" -H "Content-Type: application/json" \ -d '{"url": "https://app.example.com", "kind": "website"}'2. Add the DNS record from instructions.dns_txt, then verify
bash curl -s -X POST https://api.hardn.si/v1/targets/tgt_…/verify -H "Authorization: Bearer $HARDN_KEY"3. Start a scan and poll it
bash curl -s https://api.hardn.si/v1/scans -H "Authorization: Bearer $HARDN_KEY" -H "Content-Type: application/json" \ -d '{"target_id": "tgt_…", "scan_type": "public"}'curl -s https://api.hardn.si/v1/scans/asm_… -H "Authorization: Bearer $HARDN_KEY"4. Read the report
bash curl -s "https://api.hardn.si/v1/scans/asm_…/report?format=json" -H "Authorization: Bearer $HARDN_KEY"
Routes
Every route is scoped to the key's organisation.
| Route | Body → result |
|---|---|
| POST/targets | {"url": "https://app.example.com", "kind": "website"}201 — the site, with verification_token and instructions (DNS and file). |
| GET/targets | Your organisation's sites. |
| POST/targets/{id}/verify | {"status", "verified", "detail"} — runs the DNS or file check now. |
| POST/targets/{id}/accounts | {"label", "level", "tenant", "auth_type", "secret", "header_name"}201 — a deep-scan test account. Secrets are write-only. |
| POST/scans | {"target_id": "tgt_…", "scan_type": "public"}201 — the scan, queued. 409 target_unverified, 402 insufficient_credits. |
| GET/scans/{id} | Status, progress, and when completed: score, grade and counts. |
| GET/scans/{id}/findings | Every finding with severity, evidence and the fix. |
| GET/scans/{id}/report?format=json|html | The full report and fix report. |
Errors
Errors are JSON: {"detail": {"code": "…", "message": "…"}}.
| Status and code | What it means |
|---|---|
| 401 unauthenticated | Missing, wrong or revoked API key. |
| 402 insufficient_credits | The run isn't covered by the plan (Pro includes 500 API runs a month, Agency 3,000) and the organisation has no credits left. |
| 402 plan_limit | The plan doesn't include this, for example another site. Upgrade in Billing. |
| 404 not_found | The id doesn't exist or belongs to another organisation. |
| 409 target_unverified | Ownership hasn't been proved, or the proof has gone. |
| 422 validation_error | The body is invalid; errors lists each field. |
| 429 rate_limited | Slow down and retry after a moment. |
Use it in CI
Store the key as a secret, start a scan after each deploy, and fail the job if the grade drops below what you accept.
Watch the walkthrough: add Hardn to your CI pipeline (1:14)
- name: Hardn scan env: { HARDN_KEY: ${{ secrets.HARDN_KEY }} } run: | ID=$(curl -s https://api.hardn.si/v1/scans -H "Authorization: Bearer $HARDN_KEY" \ -H "Content-Type: application/json" \ -d '{"target_id": "tgt_…", "scan_type": "public"}' | jq -r .id) while :; do SCAN=$(curl -s https://api.hardn.si/v1/scans/$ID -H "Authorization: Bearer $HARDN_KEY") case "$(echo "$SCAN" | jq -r .status)" in queued|running) sleep 15;; *) break;; esac done GRADE=$(echo "$SCAN" | jq -r .grade) case "$GRADE" in A|B) ;; *) echo "Hardn grade $GRADE"; exit 1;; esacCreate a free account to get a key.
Command line (CLI)
The hardn command starts a scan of a verified site, waits for it, and exits 1 when it finds issues at or above the severity you choose. Python 3.9 or newer, no dependencies.
Watch the walkthrough: install the CLI and run a scan (1:02)
pip install hardn-cli # or: pipx install hardn-cliexport HARDN_API_KEY=hk_live_…hardn targets # your sites and their idshardn scan --target tgt_… --fail-on high # exit 0 pass, 1 issues found, 2 errorhardn scan --target tgt_… --sarif hardn.sarif- name: Hardn scan env: HARDN_API_KEY: ${{ secrets.HARDN_API_KEY }} run: | pip install hardn-cli hardn scan --target tgt_… --fail-on high --sarif hardn.sarifOn PyPI. Without PyPI access, install the same wheel from hardn.si (checksums).
Runtime SDK
Middleware for your own app: it labels automated-agent traffic, serves honeytokens and screens prompt injection, then reports signals to the Runtime page. Fail-open, and client IPs are hashed before they leave your process.
Watch the walkthrough: add runtime protection to your app (1:15)
# Python 3.9+pip install hardn-runtime# Node 18+npm install @hardn/runtimeimport osfrom hardn_runtime import Telemetry, Honeytokens, score_agent, scan_prompttel = Telemetry(api_key=os.environ["HARDN_API_KEY"], source="web-1")honey = Honeytokens()@app.before_requestdef guard(): sig = score_agent(user_agent=request.headers.get("User-Agent"), path=request.path, accept=request.headers.get("Accept")) if sig.is_agent: tel.record("agent_detected", ip=request.remote_addr, path=request.path, score=sig.score) if honey.is_decoy_path(request.path): tel.record("honeytoken_hit", ip=request.remote_addr, path=request.path, score=100) abort(404)const { scoreAgent, Honeytokens, scanPrompt, Telemetry } = require("@hardn/runtime");const tel = new Telemetry(process.env.HARDN_API_KEY, { source: "web-1" });app.use((req, res, next) => { const sig = scoreAgent({ userAgent: req.get("user-agent"), path: req.path, accept: req.get("accept") }); if (sig.isAgent) tel.record("agent_detected", { ip: req.ip, path: req.path, score: sig.score }); if (Honeytokens.isDecoyPath(req.path)) { tel.record("honeytoken_hit", { ip: req.ip, path: req.path, score: 100 }); return res.status(404).end(); } next();});Scan from your pipeline this week
Add your site, prove you own it, and Hardn runs 27 read-only checks. You get a grade, every issue it found and the steps to fix each one. Your first scan is free.