Skip to Content
Scan your AI agents for free·npx -y @inkog-io/cli scan .·Get Started →
APIScan

Scan Endpoint

Submit source files for security analysis and receive findings in one synchronous response.

POST /v1/scan

Analyzes source files for AI agent logic flaws and security risks. File contents travel in the JSON body: the API never reads paths on your machine.

The legacy POST /api/v1/scan endpoint is a multipart contract used internally by the CLI (it needs a request metadata part with a contract version plus files parts). Do not integrate against it directly; use POST /v1/scan with JSON as documented here, or the CLI to scan a directory.

Request

Headers:

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY
Content-TypeYesapplication/json

Body:

FieldTypeRequiredDescription
filesarrayYesOne entry per file: { "path": "src/agent.py", "content": "<file text>" }. path is used for display and framework detection; keep the repository-relative path.
policystringNobalanced (default), low-noise, comprehensive, governance, or eu-ai-act. See Security Policies.
outputstringNosummary (default), detailed, or sarif. summary and detailed return the same body today; sarif adds a sarif object.

Limits (server defaults):

LimitValue
Request body100 MB
Per-file content5 MB
Files per request10,000

Paths under tests/, examples/, docs/, and similar fixture directories are treated as test infrastructure and produce no findings. Send real source paths.

Supported file types: Python (.py), JavaScript (.js, .jsx), TypeScript (.ts, .tsx), Go (.go), YAML (.yaml, .yml), JSON (.json), and agent config formats (n8n, Flowise, Langflow, Dify exports).

Example Request

# Scan one file. The API never reads your disk: send file contents in the JSON body. curl -X POST https://api.inkog.io/v1/scan \ -H "Authorization: Bearer $INKOG_API_KEY" \ -H "Content-Type: application/json" \ -d "$(jq -n --rawfile code ./src/agent.py \ '{files: [{path: "src/agent.py", content: $code}], policy: "balanced", output: "detailed"}')"

To scan a whole directory, use the CLI (npx -y @inkog-io/cli scan .), which walks the tree, redacts secrets locally, and applies .gitignore. Language examples that send several files at once are in Code Examples.

Response

Captured from a live scan (trimmed to one finding):

{ "success": true, "scan_id": "0ed02144-783e-4edb-9303-a64e2823aa84", "risk_score": 83, "summary": { "critical": 4, "high": 11, "low": 0, "medium": 1, "total": 16 }, "files_scanned": 8, "findings": [ { "id": "IR-70", "pattern_id": "system_prompt_leak", "pattern": "System Prompt Leakage (OWASP LLM07)", "severity": "HIGH", "confidence": 0.85, "file": "src/assistants.py", "line": 70, "column": 15, "message": "System prompt contains material that should not leak (credentials, PII, internal instructions reflected from user input) or is being logged \u2026", "cwe": "CWE-209, CWE-532", "cvss": 5.5, "owasp_category": "LLM07", "category": "data_exposure", "risk_tier": "risk_pattern", "finding_type": "vulnerability", "remediation_hint": "No credentials in system prompts. No user-input echo. No plaintext logging of the prompt.", "compliance_mapping": { "eu_ai_act_articles": [ "Article 15.4" ], "nist_categories": [ "GOVERN 4.2", "MEASURE 2.7" ], "iso_42001_clauses": [ "9.2" ], "owasp_items": [ "LLM07" ], "cwe_ids": [ "CWE-209", "CWE-532" ] } } ], "quick_wins": [ { "priority": 85, "action": "Remove dangerous eval/exec - use safe parsing", "pattern_id": "exec_eval", "severity": "CRITICAL", "file": "src/dev_agent.py", "line": 69 } ] }

Response Fields

FieldTypeDescription
successbooleanWhether the scan completed
scan_idstringScan identifier; use with GET /v1/scans/{id}/diff
risk_scoreintegerOverall risk score (0-100)
summaryobjecttotal, critical, high, medium, low finding counts
files_scannedintegerFiles analyzed
files_skippedintegerPresent when files were skipped (unsupported type or fixture path)
findingsarrayFinding objects (below)
quick_winsarrayUp to five prioritized findings with a suggested action (present when there are findings)
partial_resultsbooleanPresent and true when the scan hit its time budget; warning explains what to do
sarifobjectPresent when output is sarif

Finding Object

FieldTypeDescription
idstringFinding identifier within the scan
pattern_idstringRule id, for example sql_injection
patternstringRule title
severitystringCRITICAL, HIGH, MEDIUM, or LOW
confidencenumber0.0 to 1.0
file, line, columnstring, integer, integerLocation
messagestringWhat was found and why it matters
code_snippetstringSource excerpt around the location
cwestringCWE identifiers, for example CWE-89, CWE-564
owasp_categorystringOWASP web Top 10 category when applicable (for example A03:2021)
categorystringinjection, governance, resource_exhaustion, and so on
risk_tierstringvulnerability, risk_pattern, or hardening
remediation_hint, remediation_stepsstring, arrayHow to fix it
compliance_mappingobjectowasp_items (OWASP LLM Top 10 ids), eu_ai_act_articles, nist_categories, iso_42001_clauses, cwe_ids; keys are omitted when the rule has no mapping

Severity Levels

SeverityDescription
CRITICALImmediate risk, fix before deployment
HIGHSignificant risk, fix before release
MEDIUMModerate risk, fix in normal cycle
LOWMinor risk, address when convenient

Errors

Errors are JSON with code and error:

{ "code": "auth_required", "error": "Authorization header required" }
HTTP statuscodeCause
400invalid_requestMalformed JSON, empty files, unknown policy or output, or a file over 5 MB
401auth_requiredMissing or invalid API key
413payload_too_largeBody over 100 MB
429rate limitedRetry after the Retry-After header
503worker_unavailableAnalysis worker restarting; retry

GET /v1/scans/{id}/diff

Compare a scan with the previous scan of the same agent to detect new and fixed findings. Useful for CI/CD regression tracking.

Request

Headers:

HeaderRequiredDescription
AuthorizationYesBearer YOUR_API_KEY

Query Parameters:

ParameterTypeRequiredDescription
basestringNoUUID of specific base scan to compare against (defaults to previous scan)

Response

{ "success": true, "diff": { "base_scan_id": "550e8400-e29b-41d4-a716-446655440000", "base_scan_time": "2024-01-15T10:30:00Z", "head_scan_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "head_scan_time": "2024-01-16T14:22:00Z", "summary": { "total_new": 2, "total_fixed": 1, "total_unchanged": 15, "new_by_severity": { "CRITICAL": 1, "HIGH": 1 }, "fixed_by_severity": { "HIGH": 1 }, "base_risk_score": 450, "head_risk_score": 480, "risk_delta": 30 }, "new_findings": [], "fixed_findings": [], "unchanged_findings": [] } }

Summary Fields

FieldTypeDescription
total_newintegerNumber of new findings in this scan
total_fixedintegerNumber of findings fixed since baseline
total_unchangedintegerFindings present in both scans
new_by_severityobjectBreakdown of new findings by severity
fixed_by_severityobjectBreakdown of fixed findings by severity
base_risk_scoreintegerRisk score of the baseline scan
head_risk_scoreintegerRisk score of the current scan
risk_deltaintegerChange in risk score (positive = worse)

First Scan Behavior

If this is the first scan for an agent (no previous scan exists), the response will contain:

  • base_scan_id: null
  • summary.total_new: All findings in the current scan
  • summary.total_unchanged: 0

Example Request

# Compare with previous scan (auto-detected) curl https://api.inkog.io/v1/scans/6ba7b810-9dad-11d1-80b4-00c04fd430c8/diff \ -H "Authorization: Bearer YOUR_API_KEY" # Compare with specific baseline scan curl "https://api.inkog.io/v1/scans/6ba7b810-9dad-11d1-80b4-00c04fd430c8/diff?base=550e8400-e29b-41d4-a716-446655440000" \ -H "Authorization: Bearer YOUR_API_KEY"

Regression Detection

The diff endpoint includes helper fields for regression detection:

StatusConditionDescription
REGRESSIONnew_by_severity.CRITICAL > 0 OR new_by_severity.HIGH > 0New critical/high severity findings
IMPROVEDNo regression AND (fixed_by_severity.CRITICAL > 0 OR fixed_by_severity.HIGH > 0)Fixed critical/high findings without new ones
CHANGEDNew findings but only MEDIUM/LOW severityChanges but not critical
UNCHANGEDtotal_new == 0 AND total_fixed == 0No changes
Last updated on