---
title: "Import Csv"
method: POST
path: "/claims/{claim_id}/expenditures/imports/csv"
tags: ["expenditures"]
---

# Import Csv

`POST /claims/{claim_id}/expenditures/imports/csv`

## Request

- Base URL: `https://api.claimkit.co` (the document declares no server; this is the origin it was published from)
- URL: `https://api.claimkit.co/claims/{claim_id}/expenditures/imports/csv`
- Auth: none declared

Import a CSV of expenditure items into the claim.

Admin-only. Accepts a multipart upload with ``file`` (the CSV), ``mode``
(``append`` | ``replace``), and ``column_mapping`` (JSON object mapping
target field names to CSV header names — see ``_CSV_IMPORT_TARGET_FIELDS``).

* ``append``: keeps every existing item; creates a new import record and
  inserts the parsed rows alongside.
* ``replace``: soft-deletes every active item on the claim across **every**
  prior import (Xero/QBO included) before inserting the CSV rows. The
  caller signed off on this scope. Re-running Xero/QBO will un-soft-delete
  matching rows from those sources, but any prior manual category edits on
  the wiped rows are lost.

Rows whose ``eligibility`` cell is a valid value (``r_and_d``/
``non_eligible``) are inserted with ``manual_override=True``. Rows with
blank/invalid eligibility are inserted uncategorised for the user to
categorise manually on the categorised page.

Activity-name lookup is by exact name within the claim's projects. Misses
are surfaced in ``skip_reasons`` and the row is inserted with
``activity_id = NULL``.

Auth is intentionally a *pair* of dependencies: ``get_admin_user`` checks
the real session owner (so impersonation can't elevate), and
``get_released_editable_salary_visible_claim_for_user`` checks claim
access *and* editability on the active identity. Don't collapse them.

## Path parameters

- `claim_id` integer, required

## Request body `multipart/form-data`

- BodyImportCsvClaimsClaimIdExpendituresImportsCsvPost
  - `file` string, binary, required
  - `mode` 'append' | 'replace'
  - `column_mapping` string, required

## Response `200`

Successful Response

- ImportResponse
  - `id` integer, required
  - `filename` string, nullable, required
  - `source_type` string, required
  - `source_realm` string, nullable, required
  - `last_synced_at` string, nullable, required
  - `raw_row_count` integer, required
  - `skipped_count` integer, required
  - `skip_reasons` object, nullable, required
  - `status` string, required
  - `created_at` string, required

## Other responses

- `422`: Validation Error

---

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