---
title: "Commit Import To Project"
method: POST
path: "/api/v1/import/{project_id}/from-features"
tags: ["import"]
---

# Commit Import To Project

`POST /api/v1/import/{project_id}/from-features`

Commit resolved import rows into an EXISTING project (Door 2).

Synchronous — layers exist when the response returns, like the upload
endpoint. The request carries references only: the row values come from the
held inspect result this server parsed, redeemed by ``upload.token``. Every
feature is fenced against ``projects.county_fips``: out-of-county refs are
skipped and reported per-row, in-scope rows always commit. Unknown feature
ids 404; an expired token 404s; a county-less project can't fence → 422.

## Request body

- ImportFromFeaturesRequest — Commit resolved address-import rows into an EXISTING project. Mirrors ``POST /project/sandbox/from-features`` (the new-project twin); the project's own county fences every feature server-side — out-of-county refs are skipped and reported, never fatal.
  - `upload` ImportUploadCommit, required — The held-upload half of a commit — references, never row values. The server re-reads the user's rows from its own inspect result via ``token``, so the browser's copy of the file stays display-only and the commit is not a trust boundary: no user-controlled dict keys, no reserved name collisions, no re-sanitization. ``mapped_columns`` names which held columns to carry through and is validated against the held column list.
    - `token` string, required
    - `mapped_columns` string[]
    - `matches` ImportRowMatch[], required
      - `row_index` integer, required
      - `source_table` 'parcel' | 'building' | 'place' | 'address' | 'school', required — The table a resolved feature lives in — what a caller pulls its data from, and the feature's kind. A text match in the ``address``, ``place`` or ``school`` table resolves (point-in-feature) to a ``parcel``/``building``; a ``parcel`` attribute match resolves to the parcel itself.
      - `feature_id` string, required
      - `included` boolean
    - `dropped_row_indices` integer[]
  - `spine` 'matched_only' | 'all_rows'
  - `layer_name` string, nullable — Name for the matched-features layer. Blank or absent falls back to a name derived from the matched feature ids.

## Response `200`

Successful Response

- ImportFromFeaturesResponse — Commit outcome: which refs landed and which fell outside the project's county (reported per-feature so the review UI can show the bucket).
  - `committed_feature_ids` string[], required
  - `out_of_scope_feature_ids` string[], required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/maia-analytics/apis/maia-api.md) · [All operations](https://skmtc.net/maia-analytics/apis/maia-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/maia-analytics/maia-api/versions/ba2b8d962161/schema)
