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.
| Object | Unique field | Example |
|---|---|---|
| Person | email_addresses | jane@example.com |
| Company | domains | acme.com |
| Deal | name | Acme Renewal Q1 |
| Meeting | None | Always creates |
| Task | None | Always creates |
Before you start
Three quick preparations save a lot of cleanup later:
- Create an API key in Settings → API Keys
- Export your data as CSV files (companies, contacts, deals)
- 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.
- Companies: no dependencies
- People: link to companies via
company_id - Deals: link to companies via
company_id - 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"4. Link people to deals
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
| Problem | Cause | Fix |
|---|---|---|
| 400 Duplicate record | Email or domain already exists | Pre-match and use PATCH for existing records |
422 with id field | id included in POST payload | Remove id: it's auto-generated on create |
| Enum mismatch | Value doesn't match exactly | Check casing: "Active" not "active" |
| Missing associations | Export left out linking columns | Re-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://, andwww.sodomainsgetsacme.com, nothttps://www.acme.com.