Clarify API
Guides

Import CRM Data

Suggested API call sequences for bringing CRM data into Clarify

Bringing your data into Clarify is mostly a matter of making the right API calls in the right order. This guide walks through a sequence that works well for CRM-shaped data (companies, people, and deals) wherever it's coming from: which endpoints to call, how to order them so references resolve, and the gotchas worth knowing before you press go.

Prefer clicks to curl? You can import CSV files directly in Clarify, with suggested column mappings along the way. This guide is for when you want a scripted, repeatable import you control end to end.

How records match

Each object has a unique field. Creating a record is a plain insert by default: a value that collides with an existing record's unique field is rejected with a 400. To update the existing record instead of failing, opt into upsert by passing match_on set to that unique field. Either way, you need to know which field each object matches on.

ObjectUnique fieldExample
Personemail_addressesjane@example.com
Companydomainsacme.com
DealnameAcme Renewal Q1
MeetingNoneAlways creates
TaskNoneAlways creates

Before you start

Three quick preparations save a lot of cleanup later:

  1. Create an API key in Settings → API Keys
  2. Export your data as CSV files (companies, contacts, deals)
  3. Snapshot existing records: even "empty" workspaces may have records from email sync or enrichment
# Check what's already in the workspace
curl --globoff -H "Authorization: api-key $KEY" \
  "https://api.clarify.ai/v1/workspaces/$WS/objects/person/resources?page[limit]=1"

If the workspace has existing records, you need to handle duplicates. Pass match_on with a unique field (e.g., domains for companies, email_addresses for people) to upsert into existing records, or pre-match your import data and use PATCH. Without match_on, the bulk create endpoint returns 400 on email/domain collisions.

While you're at it, give the export itself a once-over: a few minutes of cleanup beats debugging a half-finished import. See cleaning up your export below.

A suggested import sequence

Order matters: later objects reference earlier ones, so import in this sequence and every reference resolves on the first pass.

  1. Companies: no dependencies
  2. People: link to companies via company_id
  3. Deals: link to companies via company_id
  4. Associations: link people to deals via the relationships endpoint

1. Create companies

Use the bulk create endpoint to import companies in batches. The examples below pass match_on, so re-running them updates existing records instead of failing:

curl -X POST \
  -H "Authorization: api-key $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "match_on": "domains",
    "data": [
      {
        "type": "company",
        "attributes": {
          "name": "Acme Corp",
          "domains": { "items": ["acme.com"] }
        }
      }
    ]
  }' \
  "https://api.clarify.ai/v1/workspaces/$WS/objects/company/records/bulk"

Save the returned id values: you'll need them to link people and deals.

2. Create people

Same endpoint, different object. This is where those company IDs come in:

curl -X POST \
  -H "Authorization: api-key $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "match_on": "email_addresses",
    "data": [
      {
        "type": "person",
        "attributes": {
          "name": { "first_name": "Jane", "last_name": "Doe" },
          "email_addresses": { "items": ["jane@acme.com"] },
          "company_id": "c0a80121-7ac0-4b1c-8b6d-3e5f9a2d4c88"
        }
      }
    ]
  }' \
  "https://api.clarify.ai/v1/workspaces/$WS/objects/person/records/bulk"

3. Create deals

Deals also link to companies via company_id:

curl -X POST \
  -H "Authorization: api-key $KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "match_on": "name",
    "data": [
      {
        "type": "deal",
        "attributes": {
          "name": "Acme Renewal Q1",
          "amount": 50000,
          "stage": "Negotiation",
          "company_id": "c0a80121-7ac0-4b1c-8b6d-3e5f9a2d4c88"
        }
      }
    ]
  }' \
  "https://api.clarify.ai/v1/workspaces/$WS/objects/deal/records/bulk"

Last step: connect the people to the deals they belong to via the relationships endpoint.

Why a separate call, when company_id went straight into the create request? Cardinality. A person belongs to at most one company, so company_id is a to-one relationship: stored as a regular field on the person record, and settable like any other attribute. People and deals are many-to-many: one person can be on several deals and one deal involves several people, so the connection is stored between the two records rather than as a field on either one. To-many relationships like this can't be set as attributes on create (the API rejects that with a 422); they're managed through the relationships endpoint instead.

curl -X PATCH \
  -H "Authorization: api-key $KEY" \
  -H "Content-Type: application/json" \
  -d '{"data": [{"id": "5f8b7d2e-9c4a-4e1b-8f3d-2a6c9e0b4d71", "type": "person"}]}' \
  "https://api.clarify.ai/v1/workspaces/$WS/objects/deal/records/e7c9a1f4-2b8d-4c6e-9f0a-5d3b7e1c8a42/relationships/people"

That's it: your data's home.

Batching

The bulk endpoints don't cap the number of records per request: the practical ceiling is the request body size. Batches are atomic: if one record fails, the whole batch is rejected. Start with smaller batches (5–10) for your first import to catch data issues early, then scale up once the data is clean.

See bulk operations for batch sizing, rate limits, and error handling in depth.

Common pitfalls

ProblemCauseFix
400 Duplicate recordEmail or domain already existsPre-match and use PATCH for existing records
422 with id fieldid included in POST payloadRemove id: it's auto-generated on create
Enum mismatchValue doesn't match exactlyCheck casing: "Active" not "active"
Missing associationsExport left out linking columnsRe-export with association or ID columns

Cleaning up your export

CRM exports have quirks, and most import headaches trace back to one of these:

  • Association columns are often excluded by default. Before exporting, check that the columns linking contacts to companies and deals to contacts are included: without them, step 4 has nothing to work with.
  • Catch-all companies ("Website Leads", "Unknown Company") can carry hundreds of contacts. Import those contacts without a company link rather than recreating the catch-all.
  • Comma-separated emails in one cell should be split into separate values: in Clarify, an email address can belong to only one person.
  • Domains exported as full URLs need trimming. Strip http://, https://, and www. so domains gets acme.com, not https://www.acme.com.

On this page