Sync from a Warehouse
Keep Clarify in sync with your data warehouse using reverse ETL
If your warehouse is the source of truth, reverse ETL keeps Clarify current: a scheduled query picks up changed rows and pushes them to Clarify's bulk records API. Any reverse-ETL tool that can send HTTP requests to a custom destination works, and so does a scheduled job you run yourself.
How it works
- Your warehouse contains the canonical customer data
- On a schedule (hourly, daily), your pipeline queries the warehouse for changed rows
- Changed records are pushed to Clarify's bulk records API
- Each request includes
match_on, so it upserts on the object's unique field: updating an existing record when it matches, or creating a new one when it doesn't
Setup
1. Pick your pipeline
Two good options, same destination:
- A reverse-ETL tool such as Segment, Hightouch, or Census: connect your warehouse (BigQuery, Snowflake, Redshift, Databricks) as the source, and use the tool's custom HTTP or webhook destination to deliver rows to Clarify
- A scheduled job you run yourself: a cron job that queries the warehouse and POSTs the results works just as well, and gives you full control over batching and retries
2. Point the pipeline at Clarify's API
Configure your destination (or script) to send each batch of rows to Clarify's bulk records endpoint:
- Base URL
https://api.clarify.ai/v1/workspaces/{slug}/objects/{object}/records/bulk, where{slug}is your workspace slug and{object}isperson,company, ordeal - Authenticate with the header
Authorization: api-key <your-key> - Enable upsert by sending
match_onset to the object's unique field (see Matching behavior below) - Map your warehouse columns to Clarify fields
3. Define your sync model
Write a SQL query that selects the records you want to sync:
SELECT
email,
first_name,
last_name,
company_domain,
title,
lifecycle_stage
FROM analytics.contacts
WHERE updated_at > CURRENT_TIMESTAMP - INTERVAL '24 hours'4. Map fields
| Warehouse column | Clarify field | Notes |
|---|---|---|
email | email_addresses | Unique field for people |
first_name | name.first_name | |
last_name | name.last_name | |
company_domain | domains (on company) | Unique field for companies |
lifecycle_stage | Custom field | Create the field first |
5. Set a schedule
- Hourly for fast-moving data (active pipeline)
- Daily for reference data (company metadata, enrichment)
Matching behavior
Upsert is not automatic: you have to tell Clarify which field to match on by
sending match_on with each request. Set it to the object's unique field:
- People:
email_addresses - Companies:
domains - Deals:
name
When match_on is set, a matching record is updated and a new record is created
when there's no match. Without match_on, a row whose email or domain already
exists is rejected with a 400 instead of being merged, so a re-run would fail
on every record that's already in the workspace. See
how records match for the full
list of unique fields per object.
Tips
- Start with a daily sync and move to hourly once you've validated the mapping
- Dry-run with a single row first and check the record in Clarify before opening the floodgates
- Create custom fields in Clarify before mapping warehouse columns to them