---
title: "Commit an import into a list"
method: POST
path: "/business/imports/{importId}/commit"
tags: ["Lists"]
---

# Commit an import into a list

`POST /business/imports/{importId}/commit`

## Request

- Base URL: `https://api.tryfuse.ai/api/v1`
- URL: `https://api.tryfuse.ai/api/v1/business/imports/{importId}/commit`
- Auth: HTTP basic

Runs a parsed import into a list, exactly once: append to an existing list with `listId`, or name the destination with `listName` (an existing list with that exact, case-insensitive name is reused, otherwise it is created). The column mapping is resolved for every header before anything runs — your `mapping` entry first, then the suggestion stored by `POST /business/imports`, then the standard header names — and the 202 echoes the `mapping` the import ran with plus the `ignoredHeaders` it dropped. A file in which no column resolves to an identity field (LinkedIn URL, Email, or a name plus Company Domain) is refused with 422 IMPORT_IDENTITY_MISSING rather than imported as unmatched rows. `onDuplicate` decides what a row matching an existing member does: `merge` (default) fills the member's empty fields and keeps it, `skip` drops the row, `replace` saves the row as a new contact and removes the member. `enrich` runs enrichment on the imported rows in the same job (`none` = raw rows, `email`/`phone`/`phone_and_email` = the waterfall, `demographics` = resolve to canonical contacts; billed like `POST /business/lists/{listId}/enrich`). A second commit of the same importId answers 409. Async: 202. `jobId` is an opaque orchestration reference and is NOT pollable — poll `GET /business/lists/{listId}` until `completionStatus` leaves `processing`.

Errors:
- `402` `INSUFFICIENT_CREDITS` — `enrich` is `email`, `phone` or `phone_and_email` and the credit balance does not cover saving and enriching every row of the file at the reserved (worst-case) price: rows the import later drops (duplicates within the file, rows with no usable identity) are priced too. Nothing was imported or billed.
- `404` `IMPORT_NOT_FOUND` — importId does not decode to an upload of the token owner, or a presigned upload was never PUT.
- `409` `IMPORT_ALREADY_COMMITTED` — This import already ran; a commit is single-shot. Upload the file again to import it again.
- `422` `IMPORT_IDENTITY_MISSING` — After the explicit mapping, the stored suggestion and the standard header names, no column resolves to LinkedIn URL, Email, or a name plus Company Domain — rows could not be matched against the list, so nothing was imported. `param` is `mapping`.
- `422` `IMPORT_FILE_UNSUPPORTED` — A presigned upload committed without a preview call could not be parsed.
- `422` `IMPORT_FILE_TOO_LARGE` — A presigned upload committed without a preview call is over 50MB.
- `422` `IMPORT_FILE_EMPTY` — The file has no data rows.
- `404` `LIST_NOT_FOUND` — The destination listId is unknown or not owned.
- `409` `LIST_NAME_AMBIGUOUS` — More than one list carries listName — reference the destination by id.
- `422` `LIST_NAME_RESERVED` — listName is a system/dynamic list title and cannot be a destination.
- `422` `VALIDATION_FAILED` — Neither or both of listId/listName, an unknown body key, an invalid enrich or onDuplicate value, or a mapping value that is not one of the template labels.
- `429` `RATE_LIMITED` — The lists rate bucket (120 requests/minute, 10,000/day per token owner) is exhausted.

Requires one of the following token scopes: lists.

## Path parameters

- `importId` string, required: The importId returned by POST /business/imports (or /business/imports/presign) that identifies the uploaded file.

## Request body

- object
  - `listId` string: 24-character hex id of an existing contact list to append the rows to; mutually exclusive with listName, and an unknown or non-owned id answers 404 LIST_NOT_FOUND.
  - `listName` string: Name of the destination contact list (1-255 characters): an existing list with this exact name (case-insensitive) is reused, otherwise it is created; mutually exclusive with listId. Two lists sharing the name answer 409 LIST_NAME_AMBIGUOUS and reserved system titles answer 422 LIST_NAME_RESERVED.
  - `mapping` object: Column mapping from source column header to target field, e.g. {"fname": "First Name"} (up to 200 entries). Each key is a column header spelled exactly as it appears in the file (the `headers` of the import preview). Each value is one of these template labels, spelled and cased exactly like this: Full Name, First Name, Last Name, LinkedIn URL, Company, Company Domain, Job Title, Job Level, Department, Industry, Country, State, City, Email, Phone (the synonyms linkedinUrl, linkedin, Company Name, Mobile Phone, Seniority, Level are accepted and read as the label they stand for). Any other value is rejected with VALIDATION_FAILED. A header with no target carries null and is left out, so the suggestedMapping from POST /business/imports can be sent back unchanged. Headers you leave out of the mapping fall back to the stored suggestion, then to the standard header names (email, first_name, title, domain, url, position ...); the 202 response echoes the mapping the import ran with and lists every header it ignored. When two headers name the same label only the first one is used.
  - `enrich` 'none' | 'email' | 'phone' | 'phone_and_email' | 'demographics': Enrichment to run on the imported rows: none (default, rows saved exactly as uploaded), email, phone or phone_and_email (the enrichment waterfall, billed per contact processed) or demographics (resolve rows to canonical contacts, 2 credits per resolved contact).
  - `onDuplicate` 'merge' | 'skip' | 'replace': What to do with a row that matches a contact already in the destination list (matched by LinkedIn URL, then email, then name plus company domain). merge (default): fill the existing contact's empty fields from the row and keep it in the list. skip: leave the existing contact untouched and drop the row. replace: save the row as a new contact and remove the existing one from the list. With enrich set to anything but none, merge and replace both enrich the existing contact in place and skip leaves it out of the enrichment.

## Response `202`

Success

- object
  - `import` object, required
    - `importId` string, required
    - `listId` string, required
    - `jobId` string, required
    - `mapping` object, required: Source header → template label the import ran with; null for a header that was left out.
    - `ignoredHeaders` string[], required: Headers no template label claimed; their values did not reach the list.

## Other responses

- `400`: Error
- `401`: Error
- `402`: Error
- `403`: Error
- `404`: Error
- `409`: Error
- `422`: Error
- `429`: Error
- `500`: Error

---

[API](https://skmtc.dev/fuseai/apis/fuse-business-api.md) · [All operations](https://skmtc.dev/fuseai/apis/fuse-business-api/llms.txt) · [OpenAPI document](https://skmtc.dev/fuseai/apis/fuse-business-api/revisions/50d95e0536f4?raw)
