---
title: "Import contacts"
method: POST
path: "/companies/{company}/contacts/import"
tags: ["Contacts"]
---

# Import contacts

`POST /companies/{company}/contacts/import`

## Request

- Base URL: `https://api.factuarea.com/v1`
- URL: `https://api.factuarea.com/v1/companies/{company}/contacts/import`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Import contacts from CSV with target roles, field mapping, conflict strategy and optional `dry_run`.
- Returns an `import_uuid` with 200 (sync) or 202 (queued); `dry_run` is synchronous and uses no quota.
- Exhausted allowance returns 429 `import_row_quota_exceeded`; an empty file 422 subcode `empty_import`.
- CSV, TXT, XLSX or XLS up to 10 MB.

## Path parameters

- `company` string, uuid, required

## Headers

- `Idempotency-Key` string, required
- `Factuarea-Version` string, date

## Response `200`

`BusinessContactImportPreviewResource`

- object
  - `data` BusinessContactImportPreview, required
    - `source_headers` string[], required
    - `rows` object[], required
      - `row` integer, required
      - `action` 'create' | 'update' | 'add_role' | 'merge_candidate' | 'skip' | 'conflict' | 'invalid', required
      - `reason` 'already_exists' | 'duplicate_in_file' | 'merged_into_group' | 'header_row_in_data' | 'example_row' | 'no_changes' | 'merge_review_required' | 'identity_conflict' | 'validation_failed' | 'document_rows_invalid' | 'group_header_conflict' | 'concurrent_identity_taken' | 'update_not_allowed' | 'not_found_for_update' | 'null', nullable: Why the row is skipped, failed or leaves the contact unchanged; null when the row is applied.
      - `result` 'applied' | 'skipped' | 'failed': Present for confirmed execution rows; omitted from planned preview rows.
      - `target_uuid` string, uuid, nullable, required
      - `errors` object[], required
        - `param` string, nullable, required
        - `code` string, required
        - `message` string, required
      - `warnings` object[], required
        - `param` string, nullable, required
        - `code` string, required
        - `message` string, required
    - `total` integer, required
    - `create` integer, required
    - `update` integer, required
    - `add_role` integer, required
    - `merge_candidate` integer, required: Rows matching an existing contact under the `merge` strategy: nothing is applied and they are flagged for manual review (`reason=merge_review_required`).
    - `skip` integer, required: Rows that change nothing: identical to the existing contact (`no_changes`) or targeting an archived contact (`update_not_allowed`).
    - `conflict` integer, required
    - `invalid` integer, required
    - `dry_run` boolean, required
    - `import_uuid` string, uuid, nullable, required: Persisted import reference for synchronous and queued execution; null for dry-run.
    - `added_count` integer, nullable, required
    - `updated_count` integer, nullable, required
    - `skipped_count` integer, nullable, required
    - `failed_count` integer, nullable, required
    - `warnings_count` integer, nullable, required
    - `unprocessed_count` integer, nullable, required
    - `skip_reasons` object, required: Skipped rows grouped by reason (`no_changes`, `update_not_allowed`, `merge_review_required`).
    - `outcome_kind` 'changes_applied' | 'nothing_changed' | 'partial' | 'failed' | 'null', nullable, required: Business reading of a finished execution, same as the tracking resource; null for preview, dry-run and queued imports. `nothing_changed` means nothing was created or updated; do not present it as a success.
    - `status` 'queued' | 'running' | 'completed' | 'partial' | 'failed' | 'null', nullable, required: Persisted execution status; null for preview and dry-run. Synchronous responses can be failed with unprocessed rows after a concurrent closure.
    - `failure_reason` string, nullable, required
    - `queued` boolean, required

## Other responses

- `202`: Import accepted for asynchronous processing.
- `400`: The request is syntactically malformed — e.g. an unknown query parameter, an integer parameter with non-numeric value, or a value outside the documented range. `parameter_unknown` with `subcode` `retired_active_profile_header`: the retired `X-Active-Profile` header was sent; the company goes in the path. `parameter_invalid_format` on `Factuarea-Version`: the header is not a `YYYY-MM-DD` date. `unsupported_api_version`: the `Factuarea-Version` date is not a supported version.
- `401`: Missing or invalid API key.
- `403`: The request is authenticated but not allowed: the API key lacks the required scope (`insufficient_scope`), the plan does not include the public API or this feature (`addon_not_active`, `feature_not_available_in_plan`), or the module is not available with a test key (`module_not_available_in_sandbox`). `company_inactive`: the company in the path is deactivated; reactivate it to operate.
- `404`: The requested resource does not exist or belongs to another company. `profile_not_found`: the company in the path does not exist, is not in the API key scope or belongs to the other environment (live or test).
- `409`: The request conflicts with data that already exists or with a request running at the same time. `resource_already_exists` with `subcode` `tax_id_already_exists`: another contact of the company already has that fiscal identity; `details.existing_resource_id` is its identifier. `resource_already_exists` with `subcode` `external_id_already_exists`: another contact of the company already uses that `external_id`; `details.existing_resource_id` is its identifier. `resource_conflict`: another request was reserving identifiers for the same kind of record at that moment and this one could not complete its reservation. Nothing was written; send the request again after a few seconds.
- `422`: Validation failed. The `error.param` field identifies which input is invalid.
- `429`: Rate limit exceeded. Retry after the duration in `Retry-After`.
- `500`: Unexpected server error.

---

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