<a id="api-results"></a>
# 자산·Finding·Traffic API 전수 참조

asset, finding, retest, evidence snapshot과 traffic capture 영역의 등록 operation을 전수 색인한다. 이 페이지는 route/address/auth/handler 요약이고 field-level 계약은 [API 의미 schema](schema-reference.md#api-schema-reference)가 소유한다.

> **분모** · 이 페이지 49개 / 전체 261개. route 등록·auth·직접 handler는 C다. 요청/응답 semantic은 operation별 C/P/U를 분리하며 route 수를 semantic 완료율로 쓰지 않는다.

## Operation 색인

| operation | handler | auth | 입력 | status | schema |
|---|---|---|---|---|---|
| [`GET /api/assets`](#op-get-api-assets) | `listAssets` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query company_id,dsl,limit,offset,task_id,type | `200/400/401/500/503` | [P](schema-reference.md#schema-get-api-assets) |
| [`GET /api/assets/counts`](#op-get-api-assets-counts) | `assetCounts` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task_id | `200/401/500/503` | [P](schema-reference.md#schema-get-api-assets-counts) |
| [`POST /api/assets`](#op-post-api-assets) | `insertAssets` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/503` | [P](schema-reference.md#schema-post-api-assets) |
| [`DELETE /api/assets`](#op-delete-api-assets) | `deleteAssets` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/500/503` | [P](schema-reference.md#schema-delete-api-assets) |
| [`GET /api/companies`](#op-get-api-companies) | `listCompanies` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-companies) |
| [`POST /api/companies`](#op-post-api-companies) | `createCompany` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `201/400/401/409/413/500/503` | [P](schema-reference.md#schema-post-api-companies) |
| [`GET /api/companies/{id}`](#op-get-api-companies-id) | `getCompany` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500/503` | [P](schema-reference.md#schema-get-api-companies-id) |
| [`DELETE /api/companies/{id}`](#op-delete-api-companies-id) | `deleteCompany` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/500/503` | [P](schema-reference.md#schema-delete-api-companies-id) |
| [`POST /api/companies/{id}/scope`](#op-post-api-companies-id-scope) | `addCompanyScope` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/413/500/503` | [P](schema-reference.md#schema-post-api-companies-id-scope) |
| [`POST /api/companies/reattribute`](#op-post-api-companies-reattribute) | `reattribute` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [C](schema-reference.md#schema-post-api-companies-reattribute) |
| [`GET /api/exploration/frontier`](#op-get-api-exploration-frontier) | `frontier` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query limit,task | `200/401` | [P](schema-reference.md#schema-get-api-exploration-frontier) |
| [`GET /api/exploration/findings`](#op-get-api-exploration-findings) | `findings` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query asset_scope,limit,page,q,severity,sort,status,task,task_id,vulnclass | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-findings) |
| [`GET /api/exploration/findings/groups`](#op-get-api-exploration-findings-groups) | `findingGroups` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query asset_scope,limit,page,q,severity,sort,status,task_id,vulnclass | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-findings-groups) |
| [`GET /api/exploration/findings/asset-tree`](#op-get-api-exploration-findings-asset-tree) | `findingAssetTree` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query asset_scope,q,severity,sort,status,task_id,vulnclass | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-findings-asset-tree) |
| [`GET /api/exploration/findings/stats`](#op-get-api-exploration-findings-stats) | `findingStats` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-findings-stats) |
| [`GET /api/exploration/findings/export`](#op-get-api-exploration-findings-export) | `findingsExport` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query asset_scope,format,ids,q,scope,severity,sort,status,task_id,vulnclass | `200/206/304/400/401/404/409/412/416/422/500` | [P](schema-reference.md#schema-get-api-exploration-findings-export) |
| [`GET /api/exploration/findings/{id}`](#op-get-api-exploration-findings-id) | `getFinding` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query context_task | `200/400/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-findings-id) |
| [`GET /api/exploration/findings/{id}/lineage`](#op-get-api-exploration-findings-id-lineage) | `findingLineage` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-findings-id-lineage) |
| [`POST /api/exploration/findings/{id}/deepen`](#op-post-api-exploration-findings-id-deepen) | `deepenFinding` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/409/413/500` | [P](schema-reference.md#schema-post-api-exploration-findings-id-deepen) |
| [`GET /api/exploration/findings/{id}/retests`](#op-get-api-exploration-findings-id-retests) | `listFindingRetests` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500/503` | [P](schema-reference.md#schema-get-api-exploration-findings-id-retests) |
| [`GET /api/exploration/findings/retests/active`](#op-get-api-exploration-findings-retests-active) | `listActiveFindingRetests` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500/503` | [P](schema-reference.md#schema-get-api-exploration-findings-retests-active) |
| [`POST /api/exploration/findings/{id}/retests`](#op-post-api-exploration-findings-id-retests) | `startFindingRetest` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/202/400/401/404/409/413/500/503` | [P](schema-reference.md#schema-post-api-exploration-findings-id-retests) |
| [`PATCH /api/exploration/findings/{id}`](#op-patch-api-exploration-findings-id) | `patchFinding` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; JSON | `200/400/401/404/500` | [P](schema-reference.md#schema-patch-api-exploration-findings-id) |
| [`DELETE /api/exploration/findings/{id}`](#op-delete-api-exploration-findings-id) | `deleteFinding` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id | `200/400/401/404/500` | [P](schema-reference.md#schema-delete-api-exploration-findings-id) |
| [`GET /api/exploration/intents`](#op-get-api-exploration-intents) | `intents` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query before,limit,page,task | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-intents) |
| [`GET /api/exploration/graph`](#op-get-api-exploration-graph) | `explorationGraph` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-graph) |
| [`GET /api/exploration/nodes`](#op-get-api-exploration-nodes) | `explorationNodes` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query kind,order,page,q,size,state,task | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-nodes) |
| [`GET /api/exploration/activity`](#op-get-api-exploration-activity) | `activity` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query intent,limit,since,task | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-activity) |
| [`GET /api/exploration/activity/history`](#op-get-api-exploration-activity-history) | `activityHistory` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query before,limit,session,task | `200/400/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-activity-history) |
| [`GET /api/exploration/main-sessions`](#op-get-api-exploration-main-sessions) | `mainSessions` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-main-sessions) |
| [`POST /api/exploration/main-session/new`](#op-post-api-exploration-main-session-new) | `newMainSession` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/401/404/409/500` | [P](schema-reference.md#schema-post-api-exploration-main-session-new) |
| [`GET /api/exploration/activity/stream`](#op-get-api-exploration-activity-stream) | `streamActivity` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query intent,since,task | `200/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-activity-stream) |
| [`GET /api/exploration/activity/{seq}`](#op-get-api-exploration-activity-seq) | `activityDetail` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path seq; query task | `200/401/404/500` | [P](schema-reference.md#schema-get-api-exploration-activity-seq) |
| [`GET /api/exploration/tokens`](#op-get-api-exploration-tokens) | `tokenStats` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/401/500` | [P](schema-reference.md#schema-get-api-exploration-tokens) |
| [`GET /api/traffic`](#op-get-api-traffic) | `getTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query body,host,method,order,page,path,q,resp_max,resp_min,size,sort,status | `200/401` | [P](schema-reference.md#schema-get-api-traffic) |
| [`GET /api/traffic/hosts`](#op-get-api-traffic-hosts) | `getTrafficHosts` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/500` | [P](schema-reference.md#schema-get-api-traffic-hosts) |
| [`DELETE /api/traffic`](#op-delete-api-traffic) | `deleteTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query host | `200/400/401/404/500` | [P](schema-reference.md#schema-delete-api-traffic) |
| [`DELETE /api/traffic/hosts`](#op-delete-api-traffic-hosts) | `deleteTrafficHosts` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | JSON | `200/400/401/404/500` | [P](schema-reference.md#schema-delete-api-traffic-hosts) |
| [`DELETE /api/traffic/all`](#op-delete-api-traffic-all) | `deleteAllTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | none | `200/401/404/500` | [P](schema-reference.md#schema-delete-api-traffic-all) |
| [`GET /api/traffic/exchange`](#op-get-api-traffic-exchange) | `getTrafficExchange` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query id | `200/400/401/404` | [P](schema-reference.md#schema-get-api-traffic-exchange) |
| [`GET /api/traffic/blob`](#op-get-api-traffic-blob) | `getTrafficBlob` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query hash | `200/400/401/404` | [P](schema-reference.md#schema-get-api-traffic-blob) |
| [`GET /api/report`](#op-get-api-report) | `getReport` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | query task | `200/401/404` | [P](schema-reference.md#schema-get-api-report) |
| [`GET /api/exploration/findings/{id}/traffic`](#op-get-api-exploration-findings-id-traffic) | `getFindingTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query context_task | `200/400/401/404/409/422/500` | [P](schema-reference.md#schema-get-api-exploration-findings-id-traffic) |
| [`POST /api/exploration/findings/{id}/traffic`](#op-post-api-exploration-findings-id-traffic) | `bindFindingTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query context_task; JSON | `200/400/401/403/404/409/422/500` | [P](schema-reference.md#schema-post-api-exploration-findings-id-traffic) |
| [`PATCH /api/exploration/findings/{id}/traffic/{binding_id}`](#op-patch-api-exploration-findings-id-traffic-binding-id) | `editFindingTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id,binding_id; query context_task; JSON | `200/400/401/403/404/409/422/500` | [P](schema-reference.md#schema-patch-api-exploration-findings-id-traffic-binding-id) |
| [`DELETE /api/exploration/findings/{id}/traffic/{binding_id}`](#op-delete-api-exploration-findings-id-traffic-binding-id) | `editFindingTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id,binding_id; query context_task; JSON | `200/400/401/403/404/409/422/500` | [P](schema-reference.md#schema-delete-api-exploration-findings-id-traffic-binding-id) |
| [`PUT /api/exploration/findings/{id}/traffic/order`](#op-put-api-exploration-findings-id-traffic-order) | `editFindingTraffic` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id; query context_task; JSON | `200/400/401/403/404/409/422/500` | [P](schema-reference.md#schema-put-api-exploration-findings-id-traffic-order) |
| [`GET /api/exploration/findings/{id}/traffic/{binding_id}`](#op-get-api-exploration-findings-id-traffic-binding-id) | `getFindingTrafficDetail` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id,binding_id; query context_task | `200/400/401/404/409/422/500` | [P](schema-reference.md#schema-get-api-exploration-findings-id-traffic-binding-id) |
| [`GET /api/exploration/findings/{id}/traffic/{binding_id}/body`](#op-get-api-exploration-findings-id-traffic-binding-id-body) | `getFindingTrafficBody` | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 | path id,binding_id; query context_task,download,length,offset,side | `200/400/401/404/409/422/500` | [P](schema-reference.md#schema-get-api-exploration-findings-id-traffic-binding-id-body) |

<a id="op-get-api-assets"></a>
## `GET /api/assets`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `listAssets` · `server/assets.go` · [handler 근거](evidence:handler-get-api-assets) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `company_id, dsl, limit, offset, task_id, type` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-assets) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-assets-counts"></a>
## `GET /api/assets/counts`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `assetCounts` · `server/assets.go` · [handler 근거](evidence:handler-get-api-assets-counts) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task_id` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-assets-counts) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-assets"></a>
## `POST /api/assets`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `insertAssets` · `server/assets.go` · [handler 근거](evidence:handler-post-api-assets) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-assets) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-assets"></a>
## `DELETE /api/assets`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteAssets` · `server/assets.go` · [handler 근거](evidence:handler-delete-api-assets) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-assets) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-companies"></a>
## `GET /api/companies`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `listCompanies` · `server/assets.go` · [handler 근거](evidence:handler-get-api-companies) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-companies) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-companies"></a>
## `POST /api/companies`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `createCompany` · `server/assets.go` · [handler 근거](evidence:handler-post-api-companies) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `201, 400, 401, 409, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-companies) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-companies-id"></a>
## `GET /api/companies/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getCompany` · `server/assets.go` · [handler 근거](evidence:handler-get-api-companies-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-companies-id) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-delete-api-companies-id"></a>
## `DELETE /api/companies/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteCompany` · `server/assets.go` · [handler 근거](evidence:handler-delete-api-companies-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-companies-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-companies-id-scope"></a>
## `POST /api/companies/{id}/scope`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `addCompanyScope` · `server/assets.go` · [handler 근거](evidence:handler-post-api-companies-id-scope) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-companies-id-scope) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-post-api-companies-reattribute"></a>
## `POST /api/companies/reattribute`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `reattribute` · `server/assets.go` · [handler 근거](evidence:handler-post-api-companies-reattribute) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [C: 직접 scalar/static top-level key와 field type을 추출; nested 내부 schema는 별도 type 참조가 없으면 P](schema-reference.md#schema-post-api-companies-reattribute) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-exploration-frontier"></a>
## `GET /api/exploration/frontier`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `frontier` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-frontier) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `limit, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-frontier) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings"></a>
## `GET /api/exploration/findings`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findings` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-findings) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `asset_scope, limit, page, q, severity, sort, status, task, task_id, vulnclass` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-groups"></a>
## `GET /api/exploration/findings/groups`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findingGroups` · `server/findings_groups.go` · [handler 근거](evidence:handler-get-api-exploration-findings-groups) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `asset_scope, limit, page, q, severity, sort, status, task_id, vulnclass` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-groups) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-asset-tree"></a>
## `GET /api/exploration/findings/asset-tree`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findingAssetTree` · `server/findings_groups.go` · [handler 근거](evidence:handler-get-api-exploration-findings-asset-tree) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `asset_scope, q, severity, sort, status, task_id, vulnclass` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-asset-tree) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-stats"></a>
## `GET /api/exploration/findings/stats`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findingStats` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-findings-stats) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-stats) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-export"></a>
## `GET /api/exploration/findings/export`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findingsExport` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-findings-export) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `asset_scope, format, ids, q, scope, severity, sort, status, task_id, vulnclass` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 206, 304, 400, 401, 404, 409, 412, 416, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U; stdlib `412`는 body 없음, `416`은 `text/plain` (`format=md-zip` branch만 해당) |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-export) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-id"></a>
## `GET /api/exploration/findings/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getFinding` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `context_task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-id-lineage"></a>
## `GET /api/exploration/findings/{id}/lineage`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `findingLineage` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id-lineage) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id-lineage) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-exploration-findings-id-deepen"></a>
## `POST /api/exploration/findings/{id}/deepen`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deepenFinding` · `server/findings_groups.go` · [handler 근거](evidence:handler-post-api-exploration-findings-id-deepen) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 409, 413, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-exploration-findings-id-deepen) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · 후속 intent queue 접수; intent terminal state가 완료 기준 |

<a id="op-get-api-exploration-findings-id-retests"></a>
## `GET /api/exploration/findings/{id}/retests`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `listFindingRetests` · `server/finding_retests.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id-retests) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id-retests) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-retests-active"></a>
## `GET /api/exploration/findings/retests/active`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `listActiveFindingRetests` · `server/finding_retests.go` · [handler 근거](evidence:handler-get-api-exploration-findings-retests-active) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-retests-active) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-exploration-findings-id-retests"></a>
## `POST /api/exploration/findings/{id}/retests`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `startFindingRetest` · `server/finding_retests.go` · [handler 근거](evidence:handler-post-api-exploration-findings-id-retests) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 202, 400, 401, 404, 409, 413, 500, 503` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-exploration-findings-id-retests) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · retest row/conversation 시작; retest terminal state가 완료 기준 |

<a id="op-patch-api-exploration-findings-id"></a>
## `PATCH /api/exploration/findings/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `patchFinding` · `server/server.go` · [handler 근거](evidence:handler-patch-api-exploration-findings-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-patch-api-exploration-findings-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; DB upsert/trigger/side effect 때문에 반복 의미를 handler별 확인(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-exploration-findings-id"></a>
## `DELETE /api/exploration/findings/{id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteFinding` · `server/server.go` · [handler 근거](evidence:handler-delete-api-exploration-findings-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-exploration-findings-id) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-exploration-intents"></a>
## `GET /api/exploration/intents`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `intents` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-intents) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `before, limit, page, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-intents) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-graph"></a>
## `GET /api/exploration/graph`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `explorationGraph` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-graph) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-graph) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-nodes"></a>
## `GET /api/exploration/nodes`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `explorationNodes` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-nodes) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `kind, order, page, q, size, state, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-nodes) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-activity"></a>
## `GET /api/exploration/activity`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `activity` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-activity) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `intent, limit, since, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-activity) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-activity-history"></a>
## `GET /api/exploration/activity/history`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `activityHistory` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-activity-history) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `before, limit, session, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-activity-history) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-main-sessions"></a>
## `GET /api/exploration/main-sessions`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `mainSessions` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-main-sessions) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-main-sessions) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-exploration-main-session-new"></a>
## `POST /api/exploration/main-session/new`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `newMainSession` · `server/server.go` · [handler 근거](evidence:handler-post-api-exploration-main-session-new) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 409, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-exploration-main-session-new) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-exploration-activity-stream"></a>
## `GET /api/exploration/activity/stream`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `streamActivity` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-activity-stream) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `intent, since, task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-activity-stream) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · SSE 연결 수립; event lifecycle은 stream별 cursor/메모리 상태를 확인 |

<a id="op-get-api-exploration-activity-seq"></a>
## `GET /api/exploration/activity/{seq}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `activityDetail` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-activity-seq) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `seq` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-activity-seq) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-tokens"></a>
## `GET /api/exploration/tokens`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `tokenStats` · `server/server.go` · [handler 근거](evidence:handler-get-api-exploration-tokens) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-tokens) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-traffic"></a>
## `GET /api/traffic`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getTraffic` · `server/server.go` · [handler 근거](evidence:handler-get-api-traffic) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `body, host, method, order, page, path, q, resp_max, resp_min, size, sort, status` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-traffic) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-traffic-hosts"></a>
## `GET /api/traffic/hosts`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getTrafficHosts` · `server/server.go` · [handler 근거](evidence:handler-get-api-traffic-hosts) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-traffic-hosts) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-delete-api-traffic"></a>
## `DELETE /api/traffic`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteTraffic` · `server/server.go` · [handler 근거](evidence:handler-delete-api-traffic) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `host` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-traffic) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-traffic-hosts"></a>
## `DELETE /api/traffic/hosts`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteTrafficHosts` · `server/server.go` · [handler 근거](evidence:handler-delete-api-traffic-hosts) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-traffic-hosts) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-traffic-all"></a>
## `DELETE /api/traffic/all`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `deleteAllTraffic` · `server/server.go` · [handler 근거](evidence:handler-delete-api-traffic-all) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `-` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-traffic-all) |
| 반복·완료 | Idempotency-Key/If-Match 없음; 반복 시 응답/존재 검사가 달라질 수 있음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-traffic-exchange"></a>
## `GET /api/traffic/exchange`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getTrafficExchange` · `server/server.go` · [handler 근거](evidence:handler-get-api-traffic-exchange) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `id` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-traffic-exchange) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-traffic-blob"></a>
## `GET /api/traffic/blob`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getTrafficBlob` · `server/server.go` · [handler 근거](evidence:handler-get-api-traffic-blob) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `hash` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-traffic-blob) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-report"></a>
## `GET /api/report`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getReport` · `server/server.go` · [handler 근거](evidence:handler-get-api-report) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `-` · query `task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 401, 404` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-report) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-id-traffic"></a>
## `GET /api/exploration/findings/{id}/traffic`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getFindingTraffic` · `server/finding_traffic.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id-traffic) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `context_task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id-traffic) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-post-api-exploration-findings-id-traffic"></a>
## `POST /api/exploration/findings/{id}/traffic`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `bindFindingTraffic` · `server/finding_traffic.go` · [handler 근거](evidence:handler-post-api-exploration-findings-id-traffic) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `context_task` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 403, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-post-api-exploration-findings-id-traffic) |
| 반복·완료 | Idempotency-Key 없음; unique constraint 또는 상태 check가 있는 경우만 중복을 제한(P) · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-patch-api-exploration-findings-id-traffic-binding-id"></a>
## `PATCH /api/exploration/findings/{id}/traffic/{binding_id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `editFindingTraffic` · `server/finding_traffic.go` · [handler 근거](evidence:handler-patch-api-exploration-findings-id-traffic-binding-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id, binding_id` · query `context_task` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 403, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-patch-api-exploration-findings-id-traffic-binding-id) |
| 반복·완료 | body version 기반 optimistic concurrency; stale은 handler의 `409`; HTTP idempotency key는 없음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-delete-api-exploration-findings-id-traffic-binding-id"></a>
## `DELETE /api/exploration/findings/{id}/traffic/{binding_id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `editFindingTraffic` · `server/finding_traffic.go` · [handler 근거](evidence:handler-delete-api-exploration-findings-id-traffic-binding-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id, binding_id` · query `context_task` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 403, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-delete-api-exploration-findings-id-traffic-binding-id) |
| 반복·완료 | body version 기반 optimistic concurrency; stale은 handler의 `409`; HTTP idempotency key는 없음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-put-api-exploration-findings-id-traffic-order"></a>
## `PUT /api/exploration/findings/{id}/traffic/order`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `editFindingTraffic` · `server/finding_traffic.go` · [handler 근거](evidence:handler-put-api-exploration-findings-id-traffic-order) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id` · query `context_task` · body `JSON` |
| status/error | 직접 관찰 `200, 400, 401, 403, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-put-api-exploration-findings-id-traffic-order) |
| 반복·완료 | body version 기반 optimistic concurrency; stale은 handler의 `409`; HTTP idempotency key는 없음 · handler의 직접 mutation/호출 후 응답; 외부 전달·agent 실행이 파생되면 별도 상태 확인(P) |

<a id="op-get-api-exploration-findings-id-traffic-binding-id"></a>
## `GET /api/exploration/findings/{id}/traffic/{binding_id}`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getFindingTrafficDetail` · `server/finding_traffic.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id-traffic-binding-id) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id, binding_id` · query `context_task` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id-traffic-binding-id) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |

<a id="op-get-api-exploration-findings-id-traffic-binding-id-body"></a>
## `GET /api/exploration/findings/{id}/traffic/{binding_id}/body`

| 계약 | 확인 결과 |
|---|---|
| 등록·handler | `getFindingTrafficBody` · `server/finding_traffic.go` · [handler 근거](evidence:handler-get-api-exploration-findings-id-traffic-binding-id-body) |
| 인증 | JWT 필요; `extractToken`이 Bearer→cookie→query `token` 순으로 선택 |
| wire 입력 | path `id, binding_id` · query `context_task, download, length, offset, side` · body `없음(직접 body decode 미발견)` |
| status/error | 직접 관찰 `200, 400, 401, 404, 409, 422, 500` · 일반 error body `{error:string}`; helper status는 schema에서 P/U |
| 응답·validation | [P: top-level key는 직접 추출했지만 derived/helper/opaque 또는 nested type이 남음](schema-reference.md#schema-get-api-exploration-findings-id-traffic-binding-id-body) |
| 반복·완료 | read/stream 요청; stream 재연결은 cursor 계약에 따름 · 직접 조회/파일 전송 완료; 외부 조회가 있으면 응답 전 handler 결과만 보장 |
| wire 응답 branch | `download=1`은 `200` raw octet-stream attachment, 그 외는 `200 evidencePreview` JSON; `side=request|response`가 성공 조건 |

<a id="api-page-limit"></a>
## 이 페이지의 확인 한계

- route registration/auth/handler 직접 목적지는 전수 확인했다.
- field/schema/error/side-effect 의미는 별도 schema page의 C/P/U가 권위다.
- OpenAPI가 없고 실제 HTTP server는 실행하지 않았다. helper 내부·외부 서비스·DB 운영 상태는 정적 소스 이상으로 보장하지 않는다.
