Synchronise your customer data
Cycle allow you to synchronise your customer data at company level.
Initial import
If you're just getting started, you’ll want to import your existing company and user data into Cycle. Here’s how to format your CSV for import:
companyName,name,email,customId,attioId,zendeskId,hubspotId,intercomId,pipedriveId,snowflakeId,salesforceId
Acme,John Doe,[email protected],acme-001,a123,zendesk_456,hubspot_789,int_001,pipe_999,sf_acme_1,sf_001
Acme,Jane Doe,[email protected],acme-001,a123,zendesk_456,hubspot_789,int_001,pipe_999,sf_acme_1,sf_001
Wayne Enterprises,Bruce Wayne,[email protected],wayne-001,a555,zendesk_789,hubspot_321,int_003,pipe_777,sf_wayne_1,sf_003
Airbnb,Main contact,[email protected],airbnb-001,a777,zendesk_000,hubspot_000,int_004,pipe_666,sf_airbnb_1,sf_004
companyName
The name of the company
name
The full name of the person (Or `Main contact`)
Their email (or `[email protected]`)
customId (optional)
ID of your choice
attioId (optional)
ID of your Attio CRM
zendeskId (optional)
ID of your Zendesk CRM
hubspotId (optional)
ID of your HubSpot CRM
intercomId (optional)
ID of your Intercom CRM
pipedrive (optional)
ID of your Pipedrive CRM
snowflakeId (optional)
ID of your Snowflake CRM
Once your CSV is ready, you can upload it using Cycle’s GraphQL API.
Here’s the mutation to use:
graphqlCopyEditmutation importCustomersFromCSV($file: Upload!, $workspaceId: ID!) {
importCustomersFromCSV(csvFile: $file, productId: $workspaceId)
}
Examples
curl https://api.product.cycle.app/graphql \
-X POST \
-H "Authorization: Bearer YOUR_CYCLE_API_KEY" \
-F operations='{
"query": "mutation importCustomersFromCSV($file: Upload!, $workspaceId: ID!) { importCustomersFromCSV(csvFile: $file, productId: $workspaceId) }",
"variables": { "file": null, "workspaceId": "YOUR_WORKSPACE_ID" }
}' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@your_file.csv
Real-time sync with your CRM
Once your companies are in Cycle, you’ll want to keep them in sync with your CRM
For instance: When something changes in your CRM e.g. a company stage changes to “Closed Won”
Note: Using this method mean that you will make an update for each single entity you have. Since we do have a rate-limit in place you will be able to proceed with 2000 queries per hour otherwise you'll get rate-limited by our API.
Syncing updates from CRM to Cycle
Let’s say you just updated Acme’s stage to Closed Won
in your CRM.
You now want to reflect that change in Cycle.
To do that, you need to 👇
Step 1: Fetch the attribute definition ID
Before updating any company attribute, you need to retrieve the definition ID of the attribute (e.g. Stage
) 👉 In this case we assume Stage is a Select value, so you will also need the value id
GraphQL query:
query workspaceBySlug($slug: DefaultString!) {
getProductBySlug(slug: $slug) {
id
name
slug
companyAttributeDefinitions(
pagination: {
size: 100,
where: {
cursor: "",
direction: AFTER
}
}
) {
pageInfo {
endCursor
hasNextPage
}
edges {
node {
__typename
... on AttributeTextDefinition {
id
name
}
... on AttributeNumberDefinition {
id
name
}
... on AttributeCheckboxDefinition {
id
name
}
... on AttributeSingleSelectDefinition {
id
name
valuesV2(pagination: {
size: 100,
where: {
cursor: "",
direction: AFTER
}
}) {
edges {
node {
id
value
}
}
}
}
}
}
}
}
}
This will return a list of all attribute definitions available in your workspace.
Step 2: Update the company in Cycle
Once you have the attributeDefinitionId
and (if needed) the valueId
, use the following mutation:
updateCompanyAttributeValue(
$companyId: ID!
$attributeDefinitionId: ID!
$value: CompanyAttributeValueInput!
) {
updateCompanyAttributeValue(
companyId: $companyId
attributeDefinitionId: $attributeDefinitionId
value: $value
) {
__typename
... on CompanyAttributeCheckbox {
id
definition {
id
__typename
}
value {
id
valueCheckbox: value
}
}
... on CompanyAttributeText {
id
definition {
id
__typename
}
value {
id
valueText: value
}
}
... on CompanyAttributeSingleSelect {
id
definition {
id
__typename
}
value {
id
valueSelect: value
}
}
}
}
Examples
curl https://api.product.cycle.app/graphql \
-X POST \
-H "Authorization: Bearer YOUR_CYCLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation updateCompanyAttributeValue($companyId: ID!, $attributeDefinitionId: ID!, $value: CompanyAttributeValueInput!) { updateCompanyAttributeValue(companyId: $companyId, attributeDefinitionId: $attributeDefinitionId, value: $value) { __typename ... on CompanyAttributeSingleSelect { id definition { id __typename } value { id valueSelect: value } } } }",
"variables": {
"companyId": "company-id-of-acme",
"attributeDefinitionId": "definition-id-of-stage",
"value": {
"select": "value-id-for-closed-won"
}
}
}'
Create new attributes
If you need to add an attribute that does not exist yet, you first need to create it. So by using the following mutation, you are adding a "column" to your Company table so you will be able to filter on it in your dashboard.
curl https://api.product.cycle.app/graphql \
-X POST \
-H "Authorization: Bearer YOUR_CYCLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "
mutation scalarTextAttribute($workspaceId: ID!, $name: String!) {
addNewCompanyAttribute(
input: {
productId: $workspaceId
name: $name
color: \"a\"
type: { scalar: { type: TEXT } }
}
) {
__typename
}
}
",
"variables": {
"workspaceId": "YOUR_WORKSPACE_ID",
"name": "Churn reason"
}
}'
Get all existing attributes
The easiest way to get the current attributes is to fetch at the product level and use the ID
you will retrieve.
curl https://api.product.cycle.app/graphql \
-X POST \
-H "Authorization: Bearer YOUR_CYCLE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "
query workspaceBySlug($slug: DefaultString!) {
getProductBySlug(slug: $slug) {
id
name
slug
companyAttributeDefinitions(
pagination: {
size: 100,
where: {
cursor: \"\",
direction: AFTER
}
}
) {
pageInfo {
endCursor
hasNextPage
}
edges {
node {
__typename
... on AttributeTextDefinition {
id
name
}
... on AttributeNumberDefinition {
id
name
}
... on AttributeCheckboxDefinition {
id
name
}
... on AttributeSingleSelectDefinition {
id
name
valuesV2(pagination: {
size: 100,
where: {
cursor: \"\",
direction: AFTER
}
}) {
edges {
node {
id
value
}
}
}
}
}
}
}
}
}
",
"variables": {
"slug": "YOUR_WORKSPACE_SLUG"
}
}'
Daily synchronisation
A very typical way of keeping your data in-sync would be to have a cron job who run every day and update in bulk all your companies that changed during the last day.
Fetch companies from your database that were updated in the last 24 hours
Generate a CSV with those companies and the latest values
Use the mutation below to update them in bulk in Cycle
mutation updateCompanyAttributeValuesFromCSV($file: Upload!, $workspaceId: ID!) {
updateCompanyAttributeValuesFromCSV(csvFile: $file, productId: $workspaceId)
}
⚠️ You must define which column to use as the unique company identifier during the update. It can be one of these:
companyName
,customId
,attioId
,zendeskId
,hubspotId
,intercomId
,pipedriveId
,snowflakeId
,salesforceId
Cycle will use this column to match each row with an existing company in your workspace.
CSV format
Here’s an example of how your update CSV could look:
companyName customId attioId zendeskId hubspotId intercomId pipedriveId snowflakeId salesforceId arr numberOfEmployees country leadStatus industry closedDate custom attribute
Acme ... ... ... ... ... ... ... 250000 50 France Closed HR 1678670383 ...
Each column corresponds to an attribute in Cycle. You can update as many fields as you want in one go — just make sure the header names match exactly with the attribute names defined in your workspace (case-sensitive!).
Once your CSV is ready, upload it via the updateCompanyAttributeValuesFromCSV
mutation.
Last updated
Was this helpful?