BETA
Skip to content

Quickstart ​

Run your first AI security scan and triage a finding in under five minutes. This guide walks you through triggering a scan, reading the command center, browsing findings, and updating a finding's status.

Prerequisites ​

  • A Krafter account (invite-only -- request access at app.krafter.dev)
  • An API key with audit:write scope (write scope includes read access)

Step 1: Run Your First Scan ​

Trigger an AI-powered scan against a target URL. The scan must use http/https and must not target a private/loopback host (see Scans → SSRF protection).

bash
curl -X POST https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/scans/run \
  -H "Authorization: Bearer kr_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "trigger": "manual"
  }'
json
// 202 Accepted
{
  "data": {
    "id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
    "org_id": "11111111-1111-1111-1111-111111111111",
    "project_id": "production-website",
    "trigger": "manual",
    "status": "queued",
    "summary": {},
    "started_at": "2025-06-15T10:00:00Z",
    "finished_at": null,
    "inserted_at": "2025-06-15T10:00:00Z",
    "updated_at": "2025-06-15T10:00:00Z"
  },
  "meta": {
    "request_id": "F-mxbAQk6m9lXeQAAATj"
  },
  "error": null
}

Track scans by ID

The scan runs asynchronously. A 202 Accepted response means it has been queued — status will move through queued → running → completed (or failed). The submitted url is not echoed back; track the scan by id and re-fetch via GET .../audit/scans/:scan_id if you need the current state.

Rate limit

The /scans/run endpoint is throttled to 30 requests per 60-second window per team. Exceeding it returns 429 Too Many Requests with retry-after, x-ratelimit-* headers and a non-enveloped body. See Scans → Rate limit.

Step 2: Check the Command Center ​

After the scan finishes, fetch the command center for an at-a-glance health view:

bash
curl "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/command-center" \
  -H "Authorization: Bearer kr_live_abc123def456"
json
{
  "data": {
    "org_id": "11111111-1111-1111-1111-111111111111",
    "project_id": "production-website",
    "period": { "from": "2025-06-09", "to": "2025-06-15" },
    "health_score": 67,
    "unresolved_findings": 11,
    "critical_findings": 2,
    "top_priorities": [
      {
        "id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
        "title": "Missing Content-Security-Policy header",
        "severity": "critical",
        "status": "new",
        "domain": "security",
        "priority": { "impact": 80, "effort": 20, "risk": 90, "score": 88 }
      }
    ],
    "expected_impact": {
      "cwv_improvement_pct": 14,
      "security_risk_reduction_pct": 27,
      "regression_risk_pct": 16
    }
  },
  "meta": {
    "request_id": "G-nyc8sPL2vXfRBBBEUk"
  },
  "error": null
}

health_score (0–100) penalises critical and unresolved findings. top_priorities is up to five unresolved findings ordered by priority.score. See Scans → Command Center for the full field reference.

Step 3: Review Findings ​

List findings to see what the scan detected. Filter by severity, status, or domain:

bash
curl "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings?severity=critical&limit=10" \
  -H "Authorization: Bearer kr_live_abc123def456"
json
{
  "data": [
    {
      "id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
      "org_id": "11111111-1111-1111-1111-111111111111",
      "project_id": "production-website",
      "domain": "security",
      "title": "Missing Content-Security-Policy header",
      "description": "The application does not set a Content-Security-Policy header.",
      "severity": "critical",
      "status": "new",
      "confidence": 0.95,
      "priority": { "impact": 80, "effort": 20, "risk": 90, "score": 88 },
      "owner_id": null,
      "affected_assets": [
        { "type": "url", "value": "https://example.com" }
      ],
      "evidence": [],
      "recommended_fix": {
        "summary": "Add a Content-Security-Policy header to all responses.",
        "steps": ["Configure CSP at the reverse proxy", "Start with a restrictive policy", "Relax as needed"],
        "estimated_minutes": 60
      },
      "created_at": "2025-06-15T10:05:00Z",
      "updated_at": "2025-06-15T10:05:00Z"
    }
  ],
  "meta": {
    "request_id": "H-pzd9tQM3wYgSCCCFVl",
    "total": 1,
    "next_cursor": null
  },
  "error": null
}

Each finding carries a recommended_fix with concrete steps and an effort estimate. Use priority.score to order work and owner_id to assign findings.

Step 4: Triage a Finding ​

New findings start in status new. The status flow is:

new → triaged → in_progress → ready_verify → resolved
                                          ↘ dismissed

Move a finding into your queue by setting status: "triaged" (or jump straight to dismissed for false positives):

bash
curl -X PATCH "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings/d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a" \
  -H "Authorization: Bearer kr_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "triaged",
    "owner_id": "22222222-2222-2222-2222-222222222222"
  }'

The response is the full finding shape with the new status and owner_id reflected.

Don't mark "resolved" by hand

The resolved status is set automatically when an associated verification is approved. The recommended workflow is: triage → create a task → ship the fix → run a verification → approve it. Approving the verification flips the task to done, the finding to resolved, and closes any open regression for that finding.

View in the Dashboard ​

Open the Krafter dashboard at app.krafter.dev/audit to browse findings, manage tasks, and monitor your posture visually.

Next Steps ​

  • Findings Guide — Severity levels, status lifecycle, filtering, bulk operations, and regression tracking
  • Remediation Guide — Tasks, verifications, policies, integrations, and report generation

Built by Krafter Studio