# Import data

Source: https://docs.havilo.ai/mcp/imports

Use `imports_csv` when one CSV contains up to 100,000 selected data rows and 25 MiB of text. The tool validates the file and mapping synchronously, then queues durable import work when applied.

The customer catalog can inspect DataBridge connections already attached to the workspace with `databridge_workspaces_list`. It cannot create or configure a DataBridge, change its mappings, or run arbitrary preprocessing code.

## Before importing

1. Call `imports_inspect` for full-file row counts, normalized headers, blanks, duplicate counts, candidate keys, and bounded samples. For an in-app attachment, inspection needs no entity type.
2. Call `crm_schema_get` and choose the entity type by meaning. Choose a filled, unique, stable source ID, not a display name or generated row number.
3. Build a mapping from CSV column names to Havilo field IDs or exact field names.
4. Resolve missing required values, invalid field values, duplicate keys and missing relationship targets. Preserve useful unmapped columns with `note_columns`.
5. Choose a stable idempotency key for this logical import.

A CSV attachment is shown to the agent as a sample: up to 64 KiB of it, with displayed cells limited to 500 characters. A file that fits is shown whole. The context states the exact full-file counts, omitted rows and shortened cells. These display limits do not shorten imported values — `imports_inspect` and `imports_csv` read the whole file from storage by its `attachment_id`, which is why an attachment from an earlier message is named rather than repeated.

A file that mixes entity types is imported once per type. `where` selects each pass's rows, for example `[{ "column": "Type", "equals": "Organization" }]`. `relationship_mapping` links a column to a relationship, for example `{ "Company": { "relationship_type": "Fund Membership", "match": "name" } }`; the records it names must already exist, so import that type first. `note_columns` keeps each selected column under its own heading in the primary note. `note_mode: "append"` preserves existing content and avoids repeating identical imported blocks. `replace` overwrites that note and should be used only when requested.

`imports_csv` requires the external-ID column explicitly. It rejects rows without a usable external ID and rejects mappings that do not belong to the selected entity type.

## Preview

Call `imports_csv` without `apply: true`. Supply:

* `entity_type_id`;
* `file_name`;
* the file: in-app `attachment_id`, external-client `upload_token` from `imports_upload_url`, or up to 64 KiB inline in `csv`;
* `external_id_column`;
* `field_mapping`;
* `idempotency_key`.

Preview requires `ENTITY_READ`. Review the parsed headers, row count, rows left out by `where`, resolved field mapping, how many relationship targets resolve, sample rows, and payload size. Review `can_apply` and `blockers`. Invalid typed values, identity conflicts, undeclared picklist options and unresolved relationship targets block apply without creating a job. Missing columns, malformed CSV, duplicate external IDs and missing required values return an actionable tool error. A preview does not enqueue a job. Samples are bounded; counts and validation cover every selected row.

## Apply

Repeat the same reviewed input with `apply: true`. Apply requires all of:

* `BULK_OPERATIONS`;
* `ENTITY_CREATE`;
* `ENTITY_UPDATE`.

Havilo stores the validated import payload, creates the canonical import job, and returns the job ID. Reusing the same idempotency key for the same logical request returns the existing job instead of creating another import.

## Follow the job

Use `jobs_get` with the returned ID; its `progress` and `error` say where an import stopped. Workers save progress every 100 rows and enqueue a continuation before the invocation deadline. The import is complete only when the job reaches a terminal state and the imported counts match the reviewed expectation.

Read a sample of the resulting Entities with `crm_records_search` or `crm_records_get`. Verify external IDs, mapped fields, and any downstream relationships or Notes the task depended on.

## When the source needs more

Some onboarding data needs custom normalization, multiple files, a recurring connector, or a new DataBridge mapping. Contact Havilo to prepare the source or configure the connection, then use the workspace tools to inspect and verify the resulting data.

## Mapping details

Use the normalized headers returned by inspection. `Name,Name,Name_1` becomes `Name,Name_2,Name_1`; no column is discarded. Blank headers receive `Column N` names without colliding with real headers. Each target field can be mapped only once.

Use plain numbers, `true`/`false`, `YYYY-MM-DD` dates, and ISO datetimes with a timezone. Choose `list_delimiter` explicitly for list exports. Individual list values cannot exceed 255 characters; scalar field text cannot exceed 65,535 UTF-8 bytes. Keep longer source text in notes.

External IDs identify records across imports. Their uniqueness follows the database's case-insensitive comparison, including accent variants; conflicting source keys are refused before queueing. Use an existing key's exact spelling when updating. The idempotency key identifies a particular file, mapping and filtered pass. Matching also considers typed email values and supported identity URLs, never display names. Ambiguous email matches within a type are refused. If another identity matches an existing record, the imported external ID replaces its previous external ID; the preview states this policy. Review creates, updates, duplicate rows, list policy and note policy before applying.

Relationship type names are unique within a workspace. `crm_relationship_types_ensure` refuses to change an existing type's endpoint entity types. Choose a distinct name for a different pair. Entity and field creation tools expose the service's allowed icon values directly.
