Skip to main content

CRM import API

Send accounts, contacts, leads, opportunities and users to Four/Four as CSV when your CRM has no direct integration.

Written by Chris Lloyd

If your CRM is not one of the supported integrations, the CRM import API lets you send your own records as CSV. Four/Four creates or updates them and links them to conversations for filtering and segmentation. Imported records are kept as Four/Four's own CRM source, separate from records that come from connected CRMs. Records from supported CRMs arrive through their own connection, not this API.

Authentication

Create a personal access token with the Import data scope under Settings > Connections > Access tokens > Personal tokens (see the API access tokens and OAuth clients article). Send it as a Bearer token with every request. A missing or invalid token returns 401. Your workspace needs an active plan.

Endpoints

All addresses are on your Four/Four domain, for example https://fourfour.ai/import/crm/account.

Method and path

Purpose

PUT /import/crm/{type}

Create or update records. The request body is the CSV.

DELETE /import/crm/{type}

Delete records. The CSV needs only an id column.

GET /import/crm/{type}/{id}

Read one record back as a CSV with a header row and one data row. 404 if it does not exist.

GET /import/job/{job}

Check the progress of a submission.

Record types and fields

Use the type name in the path. You do not have to use every type.

Type

Fields

account

id, name, type, parent_id, website, sic, industry, currency, annual_revenue, number_of_employees, region, owner_id

contact

id, first_name, last_name, email, phone, title, account_id, department, lead_source, owner_id, region

lead

id, first_name, last_name, company, email, phone, website, lead_source, status, industry, annual_revenue, number_of_employees, owner_id, is_converted, converted_date, converted_account_id, converted_contact_id, converted_opportunity_id, account_id, region, title, currency

opportunity

id, account_id, name, description, stage_name, amount, currency, probability, expected_revenue, close_date, type, next_step, lead_source, is_closed, is_won, region, forecast_category, owner_id, contact_id

user

id, first_name, last_name, email, title. The CRM users who own records.

Any extra column not in the list is stored as an additional field and returned when you read the record back. Additional fields can be set up as custom filters in Four/Four.

CSV format

  • Send the CSV as the raw request body with content type text/csv.

  • The first row is the header. The first column must be id, your own unique identifier. Rows match on id: a new id creates a record, an existing id updates it.

  • Fields declared in the header but empty in a row are stored as empty. When updating, send every field you want to keep.

  • Dates and times: ISO 8601 in UTC. Booleans: lowercase true or false. Currencies: ISO 4217 codes such as USD.

For example, an account upload could have the header row id, name, website, industry, crm_segment (where crm_segment is an additional field), followed by one row per account such as acc-001, Acme Industries, https://acme.test, Robotics, Enterprise, comma-separated.

Processing and jobs

  • Four/Four answers 202 Accepted with a JSON body containing a job id and a Location header pointing to the job address. Keep the connection open until you receive it; if you disconnect early, nothing is queued.

  • Records are processed in the background. The job address returns a status (pending, processing, completed or failed), a processed count and timestamps. For a failed job, error describes the problem and error_line gives the row.

  • There is no hard row limit per request, but around 10,000 rows keeps uploads and jobs manageable. Send everything first, then send only changes on a schedule.

  • If a job fails part-way, rows before the failing row are already saved. Correct the CSV and resend; matching on id makes this safe.

Deleting

Send a DELETE request with a CSV containing an id column. Only records imported through this API are deleted; records from connected services are untouched.

Troubleshooting

  • 401: token missing, expired or without the Import data scope.

  • Missing "id" field in header: the first column must be named id.

  • Missing "id" field with a row number: that row has an empty id.

  • Records not visible yet: imports run in the background, so check the job status.

Permissions

Creating the personal access token needs the Manage connections permission, which admins have by default.

Did this answer your question?