---
title: "Ingest Code Scan"
method: POST
path: "/v1/projects/{project_id}/code-scan"
tags: ["code-scan"]
---

# Ingest Code Scan

`POST /v1/projects/{project_id}/code-scan`

## Request

- Base URL: `https://api.sonenta.dev`
- URL: `https://api.sonenta.dev/v1/projects/{project_id}/code-scan`
- Auth: none declared

Ingest ONE code-scan run and reconcile the project's findings (Developer+).

THE SUBMITTED SET IS AUTHORITATIVE. Every finding already known to this
project that is absent from this body is flipped to `gone`. Post the full
result of one scan, never a partial page — a truncated body retires findings
that are still hardcoded in the source.

Identity is `file + string` (+ an occurrence ordinal), **not** the line
number: a finding keeps its identity, and its `treated` mark, when code moves
around it. `line`/`column` are refreshed each run as position metadata.

A run that would retire most of the project's live findings is **refused
(422)** unless `confirm_mass_gone` is set — the usual cause is a scan over a
partial checkout, which would hide findings that are still in the code.
Every run is written to the audit log.

## Path parameters

- `project_id` string, required

## Request body

- CodeScanIngestIn
  - `findings` CodeScanFindingIn[]: EVERY hardcoded string this run found. The set is authoritative: anything known to the project and ABSENT here is marked `gone`, so a partial list silently retires findings that are still in the code.
    - `file` string, required: Repo-relative path.
    - `line` integer, required: 1-indexed line; 0 when the scanner cannot place it.
    - `column` integer, nullable
    - `string` string, required: The raw literal found.
    - `suggested_namespace` string, nullable
    - `category` string, nullable: How the scanner classified this literal: `keyless` (raw string, no key) · `key_default` (a key's defaultValue) · `unknown`. TOLERANT — omit or send any value; absent/empty is stored as `unknown`, and the roll-up folds anything that is not `keyless`/`key_default` into `unknown`. NOT part of the finding's identity.
    - `source` string, nullable: WHERE the text lives, for display: `attribute` (a placeholder/alt/title/aria-label/… value) or `element` (the parent tag/component text). TOLERANT — omit for null; any value outside {attribute, element} is stored as null, never a 422 (a client ahead of the backend must not break ingest). NOT part of identity; refreshed every run (absent → null, last-writer-wins).
    - `source_name` string, nullable: The attribute name (placeholder/alt/title/aria-label/label) or the tag/component name as written (button/label/h1/p/a/Button/Th/Foo.Bar/svg:text). Free text, TOLERANT — omit for null. NOT part of identity; refreshed every run.
  - `meta` object, nullable: Free-form run context (tool, version, sha).
  - `confirm_mass_gone` boolean: Set true ONLY when a run that retires most of the project's live findings is intended. Without it, such a run is refused (422) — the usual cause is a scan over a PARTIAL checkout, which would hide findings that are still in the code.
  - `component_prop_inventory` CodeScanInventoryItemIn[], nullable: Translatable-props inventory, PIGGYBACKED on the ingest. PRESENCE is the contract: OMITTED (null) leaves the existing inventory UNTOUCHED (an old CLI that does not know the field must not purge it); a PRESENT list — even EMPTY — is authoritative and REPLACES the project's inventory (a pair the scan did not see leaves it, an empty list clears it). Does not affect findings.
    - `component` string, required: Component/tag name as written (Button, Foo.Bar, svg:text).
    - `prop` string, required: Prop/attribute name.
    - `is_component` boolean: True when `component` is a component (PascalCase/dotted), false for a DOM tag.
    - `count` integer: How many literal-bearing occurrences were seen.
    - `samples` string[]: Up to 5 sample literal values, for the discovery preview.
    - `first_file` string, nullable
    - `first_line` integer, nullable
    - `import_source` string, nullable: The module the component is imported from (e.g. `@mui/material`); null when unknown. Tolerant, absent → null. Display only.
    - `defined_at` string, nullable: Project file path where the component is defined, when it is LOCAL; null for an external/import-sourced component. Tolerant, absent → null. Display only.

## Response `200`

Successful Response

- CodeScanRunOut
  - `scan_id` string, required
  - `created_at` string, date-time, required
  - `submitted` integer, required
  - `new` integer, required
  - `persisting` integer, required
  - `treated` integer, required
  - `gone` integer, required
  - `formula` object, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/sonenta/apis/sonenta-api.md) · [All operations](https://skmtc.dev/sonenta/apis/sonenta-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sonenta/apis/sonenta-api/revisions/f853ea49fb05?raw)
