// docs / rest api
REST API
Bearer-authenticated JSON API for passive scan automation, scan status, and findings. Cursor-paginated, rate-limited, and shipped with a machine-readable OpenAPI spec for client codegen. Active scans stay in the dashboard UI for ownership attestation.
Autenticación
Cada petición debe levar un bearer token na cabeceira Authorization. Os tokens emítense desde Account → API tokens; o texto plano móstrase exactamente unha vez ao crealo. Revogar un token devolve 401 na seguinte chamada.
curl -H "Authorization: Bearer fxw_..." \
https://fixweb.app/api/v1/scansFormato do token: fxw_ seguido de 43 caracteres base64url. Gárdase en repouso como hash SHA-256; o texto plano nunca se persiste no servidor.
Límites de taxa
Dúas ventás en cada petición autenticada: burst de 10 req/sec e steady de 60 req/min, ambas por hash bearer. A aplicación de cotas (topes mensuais de escaneo) engádese enriba; consulta Cotas e límites.
Paxinación
Os endpoints de listaxe (/api/v1/scans, /api/v1/findings) usan paxinación por cursor baseada en (created_at, id) en orde descendente. Pasa ?cursor=<next_cursor> para obter a seguinte páxina. O cursor segue correcto baixo escrituras concorrentes (sen sesgo OFFSET).
Formas de erro
Cada erro é un obxecto JSON con polo menos unha chave error.
{ "error": "invalid_token" } // 401
{ "error": "forbidden" } // 403
{ "error": "not_found" } // 404
{ "error": "quota_exceeded", "quota": {...} } // 429
{ "error": "rate_limited", "retry_after_seconds": 47 } // 429
{ "error": "invalid_input", "issues": [...] } // 400Endpoints
Iniciar un escaneo
/api/v1/scansEnqueues a passive scan. Returns immediately with a queued scan id; poll GET /api/v1/scans/[scanId] until status === "completed". Owner-depth mode is not exposed — see Scan types for the attestation-flow rationale.
curl -X POST https://fixweb.app/api/v1/scans \
-H "Authorization: Bearer fxw_..." \
-H "content-type: application/json" \
-d '{"target":"https://staging.example.com"}'// 200 response
{
"id": "8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4d",
"status": "queued",
"target": "https://staging.example.com",
"mode": "passive"
}Listar os teus escaneos
/api/v1/scansDevolve escaneos da org ligada ao token chamador, os máis novos primeiro. Paxina con ?cursor=. Límite por defecto 50, máximo 100.
curl -H "Authorization: Bearer fxw_..." \
"https://fixweb.app/api/v1/scans?limit=25"// 200 response
{
"scans": [
{
"id": "8f1c4e2a-...",
"target_url": "https://staging.example.com",
"target_hostname": "staging.example.com",
"mode": "passive",
"status": "completed",
"started_at": "2026-05-07T14:00:00Z",
"completed_at": "2026-05-07T14:00:23Z",
"findings_count": { "critical": 1, "high": 3, "medium": 7, "low": 2, "info": 4 },
"triggered_by": "api",
"created_at": "2026-05-07T14:00:00Z"
}
],
"next_cursor": "2026-05-07T14:00:00Z:8f1c4e2a-..."
}Obter un escaneo
/api/v1/scans/{scanId}Devolve por defecto envelope do escaneo + resumo de severidade por categoría. Pasa ?include_findings=true para obter o informe completo (grande en escaneos ruidosos; prefire o endpoint de findings con filtros).
curl -H "Authorization: Bearer fxw_..." \
https://fixweb.app/api/v1/scans/8f1c4e2a-8c3a-4b6f-9c0d-9b1e8f3c2a4dListar achados
/api/v1/findingsFilterable findings list across every scan in the caller's org. Filters: severity=critical,high, check_id=performance.delivery, since=2026-04-01T00:00:00Z. Cursor-paginated.
curl -H "Authorization: Bearer fxw_..." \
"https://fixweb.app/api/v1/findings?severity=critical,high&limit=50"// 200 response
{
"findings": [
{
"id": "...",
"scan_id": "...",
"check_id": "secrets.js-bundle-sweep",
"severity": "critical",
"title": "Supabase service role key exposed in JS bundle",
"description": "...",
"evidence": { ... },
"remediation": "...",
"cwe_id": "CWE-798",
"created_at": "2026-05-07T14:00:23Z"
}
],
"next_cursor": null
}Especificación OpenAPI
Especificación lexible por máquina en /docs/api/openapi (text/yaml). Metea no teu codegen favorito (openapi-typescript, openapi-python-client ou calquera toolchain OpenAPI 3.1) para clientes tipados.
