snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
---
title: Error Handling & Validation
description: Review and fix import errors directly in the UI before confirming.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## Pre-Import Validation
After uploading your file and mapping fields, Twenty validates your data **before** importing. This allows you to catch and fix errors without affecting your existing data.
## How It Works
1. **Upload** your CSV file
2. **Map** your columns to Twenty fields
3. **Review** the potential errors highlighted in yellow
4. **Fix errors** directly in the UI
5. **Confirm** the import
<VimeoEmbed videoId="1145273857" title="Video demonstration" />
## Error Display
Rows with issues are highlighted in **yellow**. You can:
- **Edit the cell directly** to fix the error
- **Remove the row** to skip it entirely
This inline editing saves time — no need to go back to your spreadsheet, fix errors, and re-upload.
## Common Error Types
### Duplicate Values
**Cause**: A unique field (email, domain) already exists in Twenty or appears twice in your file.
**Fix**:
- Edit the duplicate value in the import UI
- Remove one of the duplicate rows
See [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints) for more details on how uniqueness is enforced.
### Invalid Format
**Cause**: Data doesn't match the expected format (e.g., invalid email, wrong date format).
**Fix**: Edit the cell to use the correct format.
See [Field Mapping](/user-guide/data-migration/capabilities/field-mapping) for the expected format of each field type.
### Missing Required Fields
**Cause**: A required field is empty.
**Fix**: Enter a value in the required field or remove the row.
### Relation Not Found
**Cause**: The referenced record doesn't exist (e.g., a Company domain that wasn't imported).
**Fix**:
- Import the parent records first
- Or correct the reference value
See [Import Relations](/user-guide/data-migration/capabilities/import-relations) for the correct import order and how to link records.
## Tips for Fewer Errors
1. **Download the template** to see the expected format prior to importing your file
2. **Clean your data** in the spreadsheet first
3. **Import files in correct order** to import relations (Companies → People → Opportunities)
4. **Test with small batches** before full import
5. **Check for duplicates** before uploading
6. **Limit each file to 10,000 records**

View File

@@ -0,0 +1,164 @@
---
title: Field Mapping
description: How field mapping works during data import.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## How Field Mapping Works
When you upload a file, Twenty analyzes your columns and attempts to match them to existing fields.
### Automatic Mapping
Twenty tries to match columns based on:
- Column header names (exact or similar matches)
- Data type detection (dates, numbers, emails)
- Common field patterns
<Note>**Quick tip:** Export a few rows from the object you want to import. The exported file will have the exact column names Twenty expects, making automatic mapping seamless during import.</Note>
### Manual Mapping Options
For each column, you can:
- **Map to a field**: Select the matching Twenty field from a dropdown
- **Do not map**: Skip the column entirely (data won't be imported)
<Note>**Fields must exist before import.** The import creates records, not fields. Create custom fields under **Settings → Data Model** before importing.</Note>
## Field Type Compatibility
All field types available in the Data Model are supported for import.
You can also import `id` values to either assign a specific ID to new records or update existing ones.
<img src="/images/user-guide/fields/all-field-types.png" style={{width:'100%'}}/>
## Data Format Requirements
<Note>**Some fields have special syntax.** We recommend downloading the sample file before preparing your import to see the expected syntax for each field type.</Note>
### Address Fields
Address is a nested field with multiple columns. Some can be left empty.
- **Address / Address 1**: Street address line 1
- **Address / Address 2**: Street address line 2
- **Address / City**: City name
- **Address / State**: State or province
- **Address / Country**: Country name
- **Address / Post Code**: Postal/ZIP code
### Array Fields
Use the following format:
```
["value1","value2"]
```
### Boolean Fields
Use `TRUE` or `FALSE` (uppercase) - not `true` or `false`
### Currency Fields
Currency is a nested field with two columns that **both must be filled**:
- **Amount / Amount**: The numeric value (e.g., `1234.56`)
- **Amount / Currency**: The currency code (e.g., `USD`, `EUR`)
### Date Fields
Supported formats:
- `YYYY-MM-DD` (recommended)
- `MM/DD/YYYY`
- `DD/MM/YYYY`
- ISO 8601 format
### Domain Fields
- It is recommended to use the format `https://domain.com` to avoid creating duplicates, as this is the format used for Companies created by the mailbox and calendar synchronizations
- A `Domain Label` and `Domain URL` can be filled: best practice is to fill `domain.com` in the label and `https://domain.com` in the url
- Domains must be unique within the Companies object
- **Domains must be unique within the file to import**
### Email Fields
- Must be valid email format
- Emails must be unique within the People object
- **Emails must be unique within the file to import**
- For additional emails: use **Emails / Primary Email** for the main email, and **Emails / Additional Emails** with this format:
```
["jane@twenty.com","jane.doe@twenty.com"]
```
### ID Fields
Specifying an `id` during import is optional. Twenty auto-generates one if not provided.
Use cases for mapping an `id` column:
- **Set a specific ID**: Choose the UUID for newly created records
- **Update existing records**: Match against existing records to update them instead of creating duplicates. In that case, it is recommended to not map the other unique fields: mapping only one unique field ensures a smoother import.
<Note>If you provide an `id`, it must be in UUID format (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
### JSON Fields
Use valid JSON format:
```
{"key":"value","key2":"value2"}
```
### Links Fields
Similar to Domain fields:
- Fill both the label and URL columns: **Links / Link URL** and **Links / Link Label**
- Use full URL format: `https://example.com`
- For secondary links, use **Links / Secondary Links** column with this format:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### Multi-Select Fields
Use the **API names** (not the display labels) in the following format:
```
["VALUE1","VALUE2"]
```
See [here](#finding-api-names-for-select-fields) where to find the API names.
<Note>New select options will not be created automatically by the import. They must be added under **Settings → Data Model** before importing.</Note>
<Warning>
**Import overwrites; it does not add.**
If a record already has `VALUE2` and `VALUE3` selected, and you import `["VALUE1"]`, the record will only have `VALUE1` after import. The previous selections are replaced, not merged.
</Warning>
### Number Fields
- Numbers only
- Decimals use period: `1234.56`
- No thousands separators
### Phone Fields
Phone is a nested field with multiple columns that **must be filled**
- **Phones / Primary Phone Number**: The phone number (e.g., `4159095555`)
- **Phones / Primary Phone Country Code**: Country code (e.g., `US`)
- **Phones / Primary Phone Calling Code**: Dialing code (e.g., `+1`)
### Rating Fields
Use the API name format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, `RATING_5`
### Relation Fields
Please see our dedicated article: [Import Relations Between Objects](/user-guide/data-migration/capabilities/import-relations)
### Select Fields
Use the **API name** of the option (not the display label):
```
VALUE1
```
See [here](#finding-api-names-for-select-fields) where to find the API names.
<Note>New select options will not be created automatically by the import. They must be added under **Settings → Data Model** before importing.</Note>
### Text Fields
- No special formatting required
- Leading/trailing spaces are trimmed
## Finding API Names
For Select, Multi-Select, and Array fields with predefined options, you must use the **API names**, not the display labels.
### How to Find API Names
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at the bottom right of the settings page)
4. View the API name for each option
<VimeoEmbed videoId="1144910809" title="Video demonstration" />

View File

@@ -0,0 +1,47 @@
---
title: Supported File Formats
description: File formats supported for data import in Twenty.
---
## Supported Formats
Twenty supports three file formats for import:
| Format | Extension | Notes |
|--------|-----------|-------|
| **CSV** | .csv | Recommended, most compatible |
| **Excel** | .xlsx | Modern Excel format |
| **Excel (Legacy)** | .xls | Older Excel format |
## File Requirements
| Requirement | Value |
|-------------|-------|
| **Encoding** | UTF-8 recommended |
| **Record limit** | 10,000 records per file |
| **Structure** | First row must contain column headers |
| **Content** | One object type per file |
## CSV Best Practices
- **Delimiter**: Use comma (`,`) or semicolon (`;`)
- **Text qualifier**: Use double quotes (`"`) for text containing commas
- **Line endings**: Windows (CRLF) or Unix (LF) both supported
- **Empty values**: Leave cells empty, don't use "NULL" or "N/A"
## Excel Best Practices
When exporting from Excel:
- Remove formulas (export values only)
- Delete empty rows at the end
- Ensure no merged cells
- Use the first sheet only
## Large Datasets
For datasets larger than 10,000 records:
- Split into multiple files
- Or use the [API import](/user-guide/data-migration/how-tos/import-data-via-api) for unlimited records
<Note>For very large migrations (100,000+ records), the API is significantly faster and more reliable than CSV imports.</Note>

View File

@@ -0,0 +1,141 @@
---
title: Import Relations Between Objects
description: Import relationships between records via CSV.
---
## Overview
Twenty supports importing relationships between objects during CSV import. This allows you to link records (e.g., attach People to Companies) as part of your data migration.
<Note>**Currently supported for import**: One-to-many relations pointing to a single object type on each side (e.g., People → Companies). Relations pointing to multiple object types are not yet supported in import/export.</Note>
## How Relations Work in Twenty
### One to Many / Many to One
Twenty supports standard relations where one record links to many others:
- **One Company → Many People**: A company can have multiple employees, but each person belongs to one company
- **One Company → Many Opportunities**: A company can have multiple deals, but each opportunity belongs to one company
### Relations That Can Point to Multiple Object Types
Some relations can connect to different types of objects. This works in two ways:
**Pattern 1: Many records linking to one record each from different object types**
Several Notes or Tasks can each be attached to multiple object types at once:
- **Notes** can be linked to one Person, one Company, and one Opportunity simultaneously
- **Tasks** can be linked to one Person, one Company, and one Opportunity simultaneously
Here, the Notes/Tasks are on the "many" side. Each links to one record per object type.
<img src="/images/user-guide/fields/many-to-one-morph.png" style={{width:'100%'}}/>
**Pattern 2: One record receiving links from many records of different object types**
A Project can receive links from multiple records across different object types:
- **A Project** can have many People linked to it, many Companies linked to it, and many Notes attached to it
Here, the Project is on the "one" side. Multiple records from different objects can all link to the same Project.
<img src="/images/user-guide/fields/one-to-many-morph.png" style={{width:'100%'}}/>
<Warning>
**Import/Export limitation**: Relations that point to multiple object types (like Notes → People/Companies/Opportunities) are **not yet supported** in CSV import or export.
- **Import**: Only one-to-many relations pointing to a single object type on each side can be imported
- **Export**: Columns for relations pointing to multiple object types are currently left empty
This is on our roadmap.
</Warning>
### What's Not Supported Today
**Many to Many relations** are not yet available. For example, you cannot currently create a relation where:
- Many People are linked to many Projects
<Note>Many to Many relations are planned for H2 2026.</Note>
## Linking Records During Import
<Note>**Reminder**: Only one-to-many relations pointing to a single object type can be imported (e.g., People → Companies). Relations pointing to multiple object types (e.g., Notes → People/Companies/Opportunities) are not yet supported.</Note>
### Step 1: Identify the "One" and "Many" Sides
First, determine which object is on the "one" side and which is on the "many" side of the relationship.
**Example**:
- **Company** is the "one" side (one company has many employees)
- **People** is the "many" side (each person belongs to one company)
### Step 2: Ensure the "One" Side Records Exist
Before importing the "many" side, the "one" side records must already exist in Twenty.
- Import or create the "one" side records first (e.g., Companies)
- Validate their unique identifier. This can be:
- The `id` (Twenty's UUID)
- A field set as unique (e.g., `domain` for Companies, or an external ID from your previous system)
<Warning>The import will fail if a reference is made to a record that does not exist.</Warning>
### Step 3: Prepare Your CSV File
Add a column in your "many" side CSV file that references the "one" side record.
**Example**: For a People CSV file linking to Companies:
```
firstName,lastName,email,companyDomain
John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**Important**:
- The value must **exactly match** the unique field on the Company record
- For domains, use the **Domain URL** (e.g., `https://acme.com`), not the Domain Label
- Map only **one** unique identifier per relation: this leads to a smoother import
### Step 4: Ensure the Relation Field Exists
Before uploading your file, make sure the relation field exists between your objects.
If it doesn't exist:
1. Go to **Settings → Data Model**
2. Select your object (e.g., People)
3. Create a relation field pointing to the target object (e.g., Company)
### Step 5: Upload and Map the Relation
1. Upload your CSV file via the import UI
2. In the field mapping step, find your relation column (e.g., `companyDomain`)
3. Map it to the relation field (e.g., Company)
4. Twenty will automatically link each record to the matching parent
### Available Unique Fields for Relations
| Object | Unique Fields Available |
|--------|------------------------|
| **Companies** | `id`, `domain`, any custom unique field |
| **People** | `id`, `email`, any custom unique field |
| **Workspace Members** | `id`, `email` (not name) |
| **Other standard and custom objects** | `id`, any field marked as unique |
<Note>**Linking to Workspace Members**: When the relation points to Workspace Members (your team logging into Twenty), reference them by their **email address**, not their name.</Note>
<Note>We recommend using `domain` for Companies and `email` for People, as these are human-readable and easy to maintain in spreadsheets.</Note>
<Note>**Reminder**: Soft-deleted records (visible under Command Menu → See deleted records) count toward uniqueness criteria. If you import a record with the same unique value as a deleted record, the deleted record will be restored. See [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints) for more details.</Note>
## Import Order Rule
<Warning>
**Always import the "one" side first!**
1. **Companies** first (no dependencies)
2. **People** second (linked to Companies)
3. **Opportunities** third (linked to Companies/People)
4. **Custom objects** following their dependencies
The parent record must exist before you can reference it.
</Warning>

View File

@@ -0,0 +1,68 @@
---
title: Uniqueness Constraints
description: How Twenty enforces data uniqueness during import.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## Overview
Twenty enforces uniqueness on certain fields to prevent duplicate records and ensure data integrity. Understanding these constraints is essential for successful imports.
## Default Unique Fields
| Object | Unique Fields |
|--------|---------------|
| **People** | `id`, `email` |
| **Companies** | `id`, `domain` |
| **Custom objects** | `id` only (by default) |
<Note>The `id` field is Twenty's internal identifier, auto-generated for each record. It uses UUID format (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`).</Note>
## Custom Unique Fields
You can define additional unique fields under **Settings → Data Model**:
1. Go to **Settings → Data Model**
2. Select the object
3. Click on a field
4. Enable **Unique** in field settings
### Use Cases for Custom Unique Fields
- **External IDs**: Store IDs from other systems (Salesforce ID, HubSpot ID)
- **Business identifiers**: Employee numbers, customer codes
- **Alternative contact info**: LinkedIn profile, phone number
<Note>The field name `id` is reserved for Twenty's internal ID. Use a different name like `externalId` or `legacyId` for external identifiers.</Note>
## Import Behavior
### Creating New Records
If a unique field value doesn't exist, a new record is created.
### Updating Existing Records
If a unique field value matches an existing record, that record is **updated** with the new data.
<Warning>To **update existing records**, it is recommended to **only match one unique field**.</Warning>
### Soft-Deleted Records
<Warning>
**Deleted records count toward uniqueness.**
Soft-deleted records (visible under Command Menu → See deleted records) are included in uniqueness checks. If you import a record with the same unique value as a deleted record, the deleted record will be **restored** with the new data.
</Warning>
## Duplicate Detection During Import
During the validation phase:
- Duplicates within your file are highlighted in yellow
- You can edit or remove duplicate rows from the UI before starting the import
<VimeoEmbed videoId="1145246326" title="Video demonstration" />
## Best Practices
1. **Remove duplicates** from your file before importing
2. **Check for existing records** in Twenty before importing
3. **Use external IDs** when migrating from other systems
4. **Include unique fields** if you want to update existing records

View File

@@ -0,0 +1,32 @@
---
title: Export FAQ
description: Frequently asked questions about exporting data.
---
<AccordionGroup>
<Accordion title="Can we export all workspace data before cancellation, including custom objects, custom fields, relationships, notes, tasks, opportunities, attachments, workflows, permissions, and audit history?">
Workspace data can be exported before cancellation with some exceptions: dashboards, workflows and permissions must be transferred manually; audit logs cannot be transferred.
</Accordion>
<Accordion title="Which elements cannot currently be exported or migrated?">
Most elements can be exported or migrated with some exceptions:
- workflows, dashboards and all settings (API keys, webhooks, audit logs, user settings, etc.) must be migrated manually
- app-created objects and fields can be migrated by installing said app in a different workspace. They shouldn't be migrated manually
- some records, like workflow versions and workflow runs, are not transferable at all and are expected to be lost
- some objects like message and calendar related objects shouldn't be exported as they're created when an account is connected and synced periodically. They'll be synchronized again once you connect your account (as long as you have access to said account, if it's an account of a team member who left your company, then those messages must be exported, otherwise they'll be lost)
</Accordion>
<Accordion title="Is there an official cloud to self-hosted migration procedure or an assisted migration service?">
As of now, there is no official cloud-to-self-hosted migration procedure. The general idea is to:
- first, install apps to introduce app-owned objects and fields
- replicate custom objects and fields added by users
- use a script with API keys or AI tools to migrate all data from one workspace to another
- all non-transferrable objects must be migrated manually
Please be aware of a few things:
- you can send up to 50 requests per minute on the Pro plan or 100 requests per minute on the Organization plan before hitting a request/min limit
- each API request can have up to 200 records
- some data in fields like Created by, Timeline activities and Updated by will be lost during import and overwritten by the system
</Accordion>
<Accordion title="Are exported files provided in open and documented formats?">
Exported files in the UI are in Excel format, and all API requests can be saved in JSON format.
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,186 @@
---
title: Export Your Data
description: Complete step-by-step guide to exporting data from Twenty.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## Overview
Export your workspace data to CSV for backups, reporting, or migration.
**Use cases:**
- **Regular backups** — keep copies of your data
- **External reporting** — analyze data in Excel, Google Sheets, or BI tools
- **Migration** — move data to another system
- **Bulk updates** — export, edit, and re-import to update records
## What You Need to Know
### Export Limits
- **Maximum 20,000 records** per export
- Only **visible columns** are exported
- Only **filtered records** are exported (based on your current view)
<Note>For larger exports (20,000+ records), use filters to export in batches or use the [API](/developers/extend/api).</Note>
### Permissions
You need the **"Export CSV"** permission to export data. Contact your workspace admin if you don't have this option.
## Step 1: Navigate to the Object
Go to the object you want to export:
- **People** — for contacts
- **Companies** — for organizations
- **Opportunities** — for deals
- **Custom objects** — any object you've created
## Step 2: Configure Your View
**Important:** The export includes only what's visible in your current view.
### Add/Remove Columns
1. Click **Options → Fields** (or the **+** at the end of columns)
2. Check the fields you want to export
3. Uncheck fields you don't need
### Filter Records (Optional)
If you only need a subset of data:
1. Click **Filter**
2. Add filter conditions (e.g., "Created date > January 1, 2024")
3. Only matching records will be exported
### Sort Records (Optional)
1. Click a column header to sort
2. The export will follow your sort order
<Note>**Create a dedicated export view.** Save a view specifically configured for exports so you don't need to reconfigure each time.</Note>
## Step 3: Export the Data
1. Click the **⋮** icon on the top right of the table
2. Select **Export view**
3. Choose where to save the CSV file
4. Wait for the download to complete
## What Gets Exported
| Included | Not Included |
|----------|--------------|
| All visible columns | Hidden columns |
| Records matching current filters | Filtered-out records |
| Custom field values | Fields not in the view |
| Record IDs | File attachments |
| Relation IDs | Images |
### Relation Fields
Relation IDs are only exported on the **"many" side** of a relationship:
- **People export** includes a `companyId` column (People → Company relation)
- **Companies export** does NOT include `peopleIds` (Companies is the "one" side)
This means you can use the People export to re-import and maintain the Company link, but you'll need to re-import People after Companies to recreate the relationships.
## Exporting for Specific Purposes
### For Backups
1. Create a view with **all fields** visible
2. Remove all filters to include all records
3. Export each object type separately
4. Store exports in a secure location
5. Set a recurring reminder (weekly/monthly)
### For External Reporting
1. Include only the fields you need for analysis
2. Apply filters to focus on relevant data
3. Consider sorting by the field you'll analyze
### For Bulk Updates
1. Export the records you want to update
2. Include the unique identifier (`email`, `domain`, or `id`)
3. Edit the exported file
4. Re-import to update records
See: [How to Update Existing Records](/user-guide/data-migration/how-tos/update-existing-records-via-import)
### For Migration
If you're exporting to migrate to another system:
1. **Export each object separately** — People, Companies, Opportunities, etc.
2. **Include ID fields** — these help maintain relationships
3. **Document field mappings** — note how Twenty fields map to your target system
## Handling Large Datasets (20,000+ Records)
The export limit is 20,000 records. For larger datasets:
### Option 1: Export in Batches
1. Add a filter (e.g., "Created date" ranges)
2. Export the first batch
3. Change the filter
4. Export the next batch
5. Combine files in your spreadsheet
**Example filters for batching:**
- By date range (January, February, March...)
- By owner (Team member A, Team member B...)
- By status (Active, Inactive...)
### Option 2: Use the API
The API has no record limit:
1. Get your API key from **Settings → Developers**
2. Use the GraphQL API to query records
3. Process results in your application
See: [API Documentation](/developers/extend/api)
## Tips and Best Practices
### Create Export Views
Save views configured specifically for exports:
1. Configure columns and filters
2. Click **View options** → **Save as new view**
3. Name it "Export - [Purpose]"
### Secure Your Exports
Exported files may contain sensitive data:
- Store in secure locations
- Delete old exports when no longer needed
- Be careful sharing export files
### Check Before Exporting
<Check>Correct columns are visible</Check>
<Check>Filters are set correctly (or removed for full export)</Check>
<Check>You have Export permission</Check>
## FAQ
<AccordionGroup>
<Accordion title="Why are some columns missing from my export?">
Only visible columns are exported. Add the columns you need via **Options → Fields** before exporting.
</Accordion>
<Accordion title="Why doesn't my export have all records?">
Check your filters. The export only includes records matching your current view filters. Remove filters to export all records.
</Accordion>
<Accordion title="Can I export more than 20,000 records?">
Not in a single export. Use filters to export in batches, or use the API for larger datasets.
</Accordion>
<Accordion title="What format is the export file?">
CSV (Comma Separated Values). Opens in Excel, Google Sheets, or any spreadsheet application.
</Accordion>
<Accordion title="Are relation IDs included?">
Yes, but only on the "many" side of relationships. For example, a People export includes `companyId`, but a Companies export does not include people IDs.
</Accordion>
<Accordion title="Can I automate exports?">
Not directly through the UI. Use the API to build automated export workflows.
</Accordion>
</AccordionGroup>
## Next Steps
- [How to Update Existing Records](/user-guide/data-migration/how-tos/update-existing-records-via-import) — edit and re-import your export
- [How to Import Data via API](/user-guide/data-migration/how-tos/import-data-via-api) — for large datasets
- [API Documentation](/developers/extend/api) — build custom export workflows

View File

@@ -0,0 +1,389 @@
---
title: Fix Import Errors
description: Complete troubleshooting guide for resolving CSV import errors.
---
## Overview
Import not working? This guide helps you identify and fix common import errors step by step.
## How Import Validation Works
After uploading your file and mapping columns, Twenty validates your data:
1. **Validation runs** — Twenty checks each row for errors
2. **Errors are highlighted** — problematic rows appear in **yellow**
3. **You can fix in-place** — edit cells directly in the import UI
4. **Or remove rows** — skip problematic records entirely
<Note>**Fix errors in the UI.** You don't need to go back to your spreadsheet. Edit cells directly during import to save time.</Note>
## Step-by-Step Troubleshooting
### Step 1: Identify the Error Type
Click on a highlighted row to see the specific error message. Common error types:
| Error Message | What It Means |
|---------------|---------------|
| Duplicate values highlighted in yellow | Value already exists in Twenty or appears twice in your file |
| `{field} is not a valid {type}` (hover on yellow cell) | Data doesn't match expected format |
| Required field highlighted | A required field is empty |
| `Can't connect to {object}. No unique record found...` (import fails) | Referenced record doesn't exist |
| `Too many records. Up to 10000 allowed` (upload blocked) | File has more than 10,000 records |
### Step 2: Fix the Error
Follow the specific instructions below for each error type.
---
## Error: Duplicate Value
### What You'll See
Rows with duplicate values are **highlighted in yellow** in the import UI before the import starts.
### What It Means
A unique field (email, domain) either:
- Already exists in Twenty
- Appears twice in your file
### How to Fix
**Option 1: Edit the duplicate value**
1. Click the cell with the error
2. Change to a unique value
3. Continue with import
**Option 2: Remove the duplicate row**
1. Click the X next to the row
2. The row will be skipped during import
**Option 3: Let Twenty update the existing record**
1. Ensure your file includes a unique identifier (`email`, `domain`, or `id`)
2. Map the unique identifier field
3. Twenty will update the existing record instead of creating a duplicate
<Note>
**You can update unique fields too.**
- If you keep the `id` but change the `email` → the email will be updated
- If you keep the `email` but change the `id` → the id will be updated
As long as one unique identifier matches, Twenty updates the record.
</Note>
### How to Prevent This Error
Before importing:
1. Sort your spreadsheet by the unique field
2. Remove duplicate rows
3. Check if records already exist in Twenty
<Warning>
**Soft-deleted records count toward uniqueness.**
Check Command Menu → See deleted records. Records there still enforce uniqueness. Permanently delete them or restore and update.
</Warning>
For more details: [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints)
---
## Error: Invalid Format
### What You'll See
The cell value is highlighted in yellow. Hover over it to see the error message:
```
{field name} is not a valid {field type}
```
### What It Means
The data doesn't match the expected format for that field type.
### How to Fix — By Field Type
#### Email
**Problem:** Invalid email format
**Solution:** Use format `name@domain.com`
```
❌ john.smith@
❌ john smith@acme.com
✓ john.smith@acme.com
```
#### Domain
**Problem:** Inconsistent format may cause duplicates
**Solution:** Use `https://domain.com` format (recommended)
```
⚠️ acme.com (valid, but not recommended)
⚠️ www.acme.com (valid, but not recommended)
✅ https://acme.com (recommended)
```
<Note>All formats are valid, but `https://domain.com` is recommended because it matches the format used by email/calendar sync. Using other formats may create duplicate companies.</Note>
#### Date
**Problem:** Unrecognized date format
**Solution:** Use `YYYY-MM-DD` format consistently throughout file
```
✓ 2024-03-15 (YYYY-MM-DD)
❌ 03/15/2024 (MM/DD/YYYY)
❌ 15/03/2024 (DD/MM/YYYY)
```
#### Phone
**Problem:** Missing required columns
**Solution:** Include all phone columns
| Column | Example |
|--------|---------|
| **Phones / Primary Phone Number** | `4159095555` |
| **Phones / Primary Phone Country Code** | `US` |
| **Phones / Primary Phone Calling Code** | `+1` |
#### Boolean
**Problem:** Wrong boolean value
**Solution:** Use uppercase `TRUE` or `FALSE`
```
❌ true
❌ yes
❌ 1
✓ TRUE
✓ FALSE
```
#### Select / Multi-Select
**Problem:** Value doesn't match existing options
**Solution:** Use **API names**, not display labels
How to find API names:
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at bottom right)
4. Use the API name (e.g., `OPTION_1`, not "Option 1")
```
❌ High Priority
✓ HIGH_PRIORITY
```
#### Currency
**Problem:** Missing amount or currency code
**Solution:** Fill both columns
| Column | Example |
|--------|---------|
| **Amount / Amount** | `1234.56` |
| **Amount / Currency** | `USD` |
#### Number
**Problem:** Non-numeric characters
**Solution:** Numbers only, period for decimals
```
❌ $1,234.56
❌ 1,234.56
✓ 1234.56
```
For complete format reference: [Field Mapping](/user-guide/data-migration/capabilities/field-mapping)
---
## Error: Required Field Missing
### What You'll See
The row is highlighted in yellow with the required field cell marked.
### What It Means
A required field is empty for this row.
### How to Fix
**Option 1: Enter a value**
1. Click the empty cell
2. Enter a value
3. Continue with import
**Option 2: Remove the row**
1. If you don't have the data, click X to skip the row
### How to Prevent This Error
Before importing, identify required fields:
1. Go to **Settings → Data Model**
2. Select your object
3. Check which fields are marked as required
---
## Error: Relation Not Found
### What You'll See
This error appears **after the import starts** — the import fails with a message like:
```
Can't connect to company. No unique record found with condition: id = 7776ee49-f608-4a77-8cc8-6fe96ae1e43f
```
This means there is no Company in Twenty with that specific identifier.
<Note>Unlike other errors, this one is not caught during the data review step. The import will start and then fail when it encounters the missing relation.</Note>
### What It Means
You're trying to link to a record that doesn't exist in Twenty.
### How to Fix
**Option 1: Import parent records first**
1. Cancel the current import
2. Import the parent records (e.g., Companies)
3. Then import the child records (e.g., People)
**Option 2: Fix the reference value**
1. Check the reference value in your file
2. Ensure it exactly matches an existing record
3. Verify format: domains should be `https://domain.com`
**Option 3: Remove the relation**
1. Clear the cell to import without the relation
2. Add the relation manually later
### How to Prevent This Error
1. **Import in the correct order:**
- Companies first
- People second (with company references)
- Opportunities third
2. **Verify reference values:**
- Export parent records to get exact identifiers
- Use domain format `https://domain.com`
- Check for typos and case sensitivity
<Warning>
**Import will fail if a reference is made to a non-existent record.**
Always import parent objects before child objects.
</Warning>
For more details: [Import Relations](/user-guide/data-migration/capabilities/import-relations)
---
## Error: File Too Large
### What You'll See
This error appears **when uploading your file** — the upload is blocked entirely:
```
Too many records. Up to 10000 allowed
```
You won't be able to proceed to the data review step until you reduce the file size.
### What It Means
Your file has more than 10,000 records.
### How to Fix
**Option 1: Split into multiple files**
1. Divide your data into files of 10,000 records or fewer
2. Import each file separately
3. Maintain import order (Companies before People)
**Option 2: Use API import**
For very large datasets, use the API which has no record limit.
See: [How to Import Data via API](/user-guide/data-migration/how-tos/import-data-via-api)
---
## Error: Field Not Recognized
### What It Means
A column in your file can't be mapped because the field doesn't exist in Twenty.
### How to Fix
1. Go to **Settings → Data Model**
2. Select the object you're importing
3. Click **+ Add field**
4. Create the custom field with the appropriate type
5. Re-upload your file
<Note>The CSV import creates records, not fields. All fields must exist before importing.</Note>
---
## Error: User Relation Empty
### What It Means
You're trying to assign a record to a user (Owner, Assignee) but the relation isn't being mapped.
### Common Causes
1. **User hasn't accepted their invitation** — the user doesn't exist in Twenty yet
2. **Using user ID from old system** — Twenty can't match IDs from another system
3. **Wrong email format** — the email doesn't match the user's Twenty account
### How to Fix
1. Ensure all users have **accepted their invitation** to your Twenty workspace
2. Use the user's **email address** (not their name or old system ID)
3. Use the same email they used to join Twenty
<Warning>
**Users must accept invitations before importing.**
If a user hasn't accepted their invitation, records referencing them will have empty user relations.
</Warning>
---
## Pre-Import Checklist
Avoid errors by checking these before importing:
### File Requirements
<Check>File is CSV, XLSX, or XLS format</Check>
<Check>File has fewer than 10,000 records</Check>
<Check>File uses UTF-8 encoding</Check>
### Data Quality
<Check>No duplicate emails (for People)</Check>
<Check>No duplicate domains (for Companies)</Check>
<Check>All dates use consistent format</Check>
<Check>All domains use `https://domain.com` format</Check>
### Field Formats
<Check>Boolean fields use `TRUE` or `FALSE` (uppercase)</Check>
<Check>Select fields use API names, not display labels</Check>
<Check>Phone fields have all required columns</Check>
<Check>Currency fields have both Amount and Currency Code</Check>
### Relations
<Check>Parent records imported before child records</Check>
<Check>Relation columns reference existing records</Check>
<Check>Domain format matches Twenty's format exactly</Check>
### Data Model
<Check>All custom fields exist in Settings → Data Model</Check>
<Check>Select options exist before importing</Check>
---
## Still Having Issues?
If you've tried the above solutions:
1. **Download the sample file** — see the exact format Twenty expects
2. **Export existing records** — compare your file to working data
3. **Test with a small batch** — try 5-10 rows first
4. **Check the reference articles:**
- [Field Mapping](/user-guide/data-migration/capabilities/field-mapping)
- [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints)
- [Import Relations](/user-guide/data-migration/capabilities/import-relations)
- [Error Handling](/user-guide/data-migration/capabilities/error-handling)

View File

@@ -0,0 +1,192 @@
---
title: Import Companies via CSV
description: Complete step-by-step guide to importing companies into Twenty.
---
## Overview
This guide walks you through importing your companies into Twenty. **Companies should be imported first** because People and Opportunities link to Companies.
## Before You Start
### Prerequisites Checklist
<Check>
Your file is CSV, XLSX, or XLS format
</Check>
<Check>
File has fewer than 10,000 records
</Check>
<Check>
No duplicate domains in your file
</Check>
<Check>
All custom fields exist in **Settings → Data Model**
</Check>
<Note>
Need to import more than 10,000 companies? Split into multiple files or use the [API import](/user-guide/data-migration/how-tos/import-data-via-api).
</Note>
## Step 1: Prepare Your Company Data
### Required and Recommended Fields
| Field | Required? | Format | Notes |
|-------|-----------|--------|-------|
| **Name** | Recommended | Text | Company display name |
| **Domain** | Recommended | `https://domain.com` | Unique identifier |
| **Address** | Optional | Multiple columns | See below |
| **Employees** | Optional | Number | Employee count |
| **Custom fields** | Optional | Varies | Must exist in Data Model |
### Domain Format
<Warning>
**Use the format `https://domain.com` for domains.**
This matches the format used when Companies are auto-created from email/calendar sync, preventing duplicates later.
</Warning>
**Domain columns:**
- **Domain / Domain Label**: `acme.com`
- **Domain / Domain URL**: `https://acme.com`
### Address Format
Address is a nested field with multiple columns:
```
Address / Address 1,Address / City,Address / State,Address / Country,Address / Post Code
123 Main Street,San Francisco,CA,USA,94105
```
### Sample CSV Structure
```csv
name,Domain / Domain URL,Domain / Domain Label,Address / City,Address / Country,employees
Acme Corp,https://acme.com,acme.com,San Francisco,USA,250
Widget Co,https://widgets.co,widgets.co,New York,USA,50
```
<Note>
**Pro tip:** Click **Download sample file** during import to see the exact column names Twenty expects.
</Note>
## Step 2: Access the Import Feature
**Option 1: From the Companies View**
1. Navigate to **Companies** in the left sidebar
2. Click the **⋮** icon on the top right
3. Select **Import records**
**Option 2: Using Command Menu**
1. Press `Cmd + K` (Mac) or `Ctrl + K` (Windows)
2. Type "import"
3. Select **Import records**
4. Choose **Companies**
## Step 3: Upload Your File
1. Click **Select file**
2. Choose your CSV, XLSX, or XLS file
3. Wait for Twenty to analyze your file
## Step 4: Map Your Columns
Twenty automatically tries to match your columns to fields. Review and adjust:
1. **Check automatic mappings** — verify they're correct
2. **Fix incorrect mappings** — click the dropdown to select the right field
3. **Skip columns** — select **Do not map** for columns you don't want to import
### Important Mapping Rules
- **Domain**: Map to **Domain / Domain URL** (not Domain Label)
- **Address**: Map each part to its specific column (City, State, etc.)
- **Select fields**: Values must match existing options (or you'll map them in the next step)
<img src="/images/user-guide/import-export-data/match-columns.png" style={{width:'100%'}}/>
## Step 5: Map Select Field Values
If you have Select or Multi-Select fields:
1. Twenty shows your values alongside existing options
2. Match each value in your file to a Twenty option
3. Or create new options if needed
<Note>
Select options use **API names**, not display labels. Check **Settings → Data Model** → Enable **Advanced mode** to see API names.
</Note>
## Step 6: Review and Fix Errors
Before completing the import, Twenty validates your data:
1. Click **Next Steps**
2. Rows with errors are highlighted in **yellow**
3. **Fix errors directly** — click a cell and edit the value
4. **Remove problematic rows** — click the X to skip that row
### Common Company Import Errors
| Error | Cause | Solution |
|-------|-------|----------|
| **Duplicate domain** | Domain already exists in Twenty | Remove from file or update existing record |
| **Invalid domain format** | Wrong format | Use `https://domain.com` |
| **Missing required field** | Required field is empty | Fill in the value or remove the row |
## Step 7: Complete the Import
1. Review the import summary
2. Click **Confirm** to import
3. Wait for the import to complete
4. Verify by checking a few records
## After Importing Companies
Now you can import records that link to Companies:
1. **[Import People](/user-guide/data-migration/how-tos/import-contacts-via-csv)** — link them to Companies using the domain
2. **Import Opportunities** — link them to Companies
3. **Verify the import** — spot-check a few records to ensure data is correct
## Updating Existing Companies
To update companies instead of creating new ones:
1. Include the `domain` or `id` column in your file
2. Twenty matches records by this unique identifier
3. Existing companies are updated; new ones are created
See [How to Update Existing Records](/user-guide/data-migration/how-tos/update-existing-records-via-import) for details.
## FAQ
<AccordionGroup>
<Accordion title="Why can't two Companies have the same domain?">
Domain is a unique identifier in Twenty. This prevents duplicate companies and ensures email sync correctly links emails to the right company.
</Accordion>
<Accordion title="What if I have companies without a domain?">
You can leave the domain empty. However, we recommend adding domains when possible for better data quality and automatic email linking.
</Accordion>
<Accordion title="Can I import companies without any People linked?">
Yes! You can import companies first, then import People later and link them using the company domain.
</Accordion>
<Accordion title="What happens if I import a domain that already exists?">
If you include a unique identifier (domain or id) that matches an existing company, Twenty updates that company instead of creating a duplicate.
</Accordion>
<Accordion title="How do I fix 'duplicate domain' errors?">
Either remove the duplicate from your file, or include the company's `id` to update the existing record instead.
</Accordion>
</AccordionGroup>
## Troubleshooting
Having issues? Check:
- [How to Fix Import Errors](/user-guide/data-migration/how-tos/fix-import-errors)
- [Field Mapping Reference](/user-guide/data-migration/capabilities/field-mapping)
- [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints)

View File

@@ -0,0 +1,232 @@
---
title: Import Contacts via CSV
description: Complete step-by-step guide to importing people/contacts into Twenty.
---
## Overview
This guide walks you through importing your contacts (People) into Twenty.
## Before You Start
### Prerequisites Checklist
<Check>
Your file is CSV, XLSX, or XLS format
</Check>
<Check>
File has fewer than 10,000 records
</Check>
<Check>
No duplicate email addresses in your file
</Check>
<Check>
**Companies imported first** (if linking People to Companies)
</Check>
<Check>
All custom fields exist in **Settings → Data Model**
</Check>
<Warning>
**Import Companies Before People**
If you want to link People to Companies, import Companies first. The Company must exist before you can reference it.
</Warning>
## Step 1: Prepare Your Contact Data
### Required and Recommended Fields
| Field | Required? | Format | Notes |
|-------|-----------|--------|-------|
| **Email** | Recommended | `name@domain.com` | Must be unique |
| **First Name** | Recommended | Text | |
| **Last Name** | Recommended | Text | |
| **Company** | Optional | Domain or ID | Links to existing Company |
| **Phone** | Optional | Multiple columns | See below |
| **Job Title** | Optional | Text | |
| **Custom fields** | Optional | Varies | Must exist in Data Model |
### Email Format
- Must be valid email format: `name@domain.com`
- **Must be unique** — no duplicates in your file or in Twenty
- For additional emails, use the **Emails / Additional Emails** column:
```
["jane@twenty.com","jane.doe@twenty.com"]
```
### Phone Format
Phone is a **nested field** requiring multiple columns:
| Column | Example |
|--------|---------|
| **Phones / Primary Phone Number** | `4159095555` |
| **Phones / Primary Phone Country Code** | `US` |
| **Phones / Primary Phone Calling Code** | `+1` |
### Linking to Companies
Add a column with the Company's unique identifier:
| Column Name | Format | Example |
|-------------|--------|---------|
| `companyDomain` | URL format | `https://acme.com` |
| `companyId` | UUID | `c776ee49-f608-4a77-8cc8-6fe96ae1e43f` |
<Note>
**Use Domain URL format** (`https://acme.com`), not the label. This matches how Companies are stored in Twenty.
</Note>
### Sample CSV Structure
```csv
firstName,lastName,email,jobTitle,companyDomain,Phones / Primary Phone Number,Phones / Primary Phone Country Code
John,Smith,john@acme.com,CEO,https://acme.com,4159095555,US
Jane,Doe,jane@widgets.co,CTO,https://widgets.co,2125551234,US
```
<Note>
**Pro tip:** Click **Download sample file** during import or export a few existing People to see the exact column names Twenty expects.
</Note>
## Step 2: Access the Import Feature
**Option 1: From the People View**
1. Navigate to **People** in the left sidebar
2. Click the **⋮** icon on the top right
3. Select **Import records**
**Option 2: Using Command Menu**
1. Press `Cmd + K` (Mac) or `Ctrl + K` (Windows)
2. Type "import"
3. Select **Import records**
4. Choose **People**
## Step 3: Upload Your File
1. Click **Select file**
2. Choose your CSV, XLSX, or XLS file
3. Wait for Twenty to analyze your file
## Step 4: Map Your Columns
Twenty automatically tries to match your columns to fields. Review and adjust:
1. **Check automatic mappings** — verify they're correct
2. **Fix incorrect mappings** — click the dropdown to select the right field
3. **Skip columns** — select **Do not map** for columns you don't want to import
### Important Mapping Rules
| Column Type | Map To | Notes |
|-------------|--------|-------|
| Company reference | **Company** relation field | Use domain OR id, not both |
| Email | **Email** | Primary email address |
| Additional emails | **Emails / Additional Emails** | Array format |
| Phone | Separate columns | Number, Country Code, Calling Code |
<img src="/images/user-guide/import-export-data/match-columns.png" style={{width:'100%'}}/>
### Mapping the Company Relation
When mapping the company column:
1. Find your company reference column (e.g., `companyDomain`)
2. Map it to the **Company** relation field
3. Twenty will link each Person to the matching Company
<Warning>
**Map only ONE unique identifier for relations.**
Don't map both `companyId` AND `companyDomain`. Choose one—preferably domain since it's human-readable.
</Warning>
## Step 5: Map Select Field Values
If you have Select or Multi-Select fields (like Lead Source):
1. Twenty shows your values alongside existing options
2. Match each value in your file to a Twenty option
3. Or create new options if needed
<Note>
Select options use **API names**, not display labels. Check **Settings → Data Model** → Enable **Advanced mode** to see API names.
</Note>
## Step 6: Review and Fix Errors
Before completing the import, Twenty validates your data:
1. Click **Next Steps**
2. Rows with errors are highlighted in **yellow**
3. **Fix errors directly** — click a cell and edit the value
4. **Remove problematic rows** — click the X to skip that row
### Common Contact Import Errors
| Error | Cause | Solution |
|-------|-------|----------|
| **Duplicate email** | Email already exists in Twenty or file | Remove duplicate or update existing record |
| **Invalid email format** | Email format incorrect | Fix to `name@domain.com` |
| **Relation not found** | Company doesn't exist | Import Companies first or fix the reference |
| **Missing required field** | Required field is empty | Fill in the value or remove the row |
## Step 7: Complete the Import
1. Review the import summary
2. Click **Confirm** to import
3. Wait for the import to complete
4. Verify by checking a few records and their Company links
## After Importing Contacts
Your contacts are now in Twenty! Next steps:
1. **Verify Company links** — open a few People records to confirm they're linked to the right Company
2. **Import Opportunities** — if needed, link them to People and Companies
3. **Set up email sync** — connect your mailbox to see email history on contact records
## Updating Existing Contacts
To update contacts instead of creating new ones:
1. Include the `email` or `id` column in your file
2. Twenty matches records by this unique identifier
3. Existing contacts are updated; new ones are created
See [How to Update Existing Records](/user-guide/data-migration/how-tos/update-existing-records-via-import) for details.
## FAQ
<AccordionGroup>
<Accordion title="Why can't two People have the same email?">
Email is a unique identifier in Twenty. This prevents duplicate contacts and ensures email sync correctly links emails to the right person.
</Accordion>
<Accordion title="What if I have people without an email?">
You can leave the email empty. However, we recommend adding emails when possible for better data quality and email sync functionality.
</Accordion>
<Accordion title="How do I link People to Companies during import?">
Add a column with the Company's domain (e.g., `https://acme.com`) or ID. During mapping, connect this column to the Company relation field.
</Accordion>
<Accordion title="What if the Company doesn't exist yet?">
Import Companies first, then import People. The Company must exist before you can reference it.
</Accordion>
<Accordion title="Can I import the ID from my previous CRM?">
Yes! Create a custom field marked as "unique" in your data model to store the external ID. Note: the field name `id` is reserved for Twenty's internal ID.
</Accordion>
<Accordion title="How do I fix 'relation not found' errors?">
The Company you're referencing doesn't exist. Either import the Company first, or check that the domain/ID exactly matches an existing Company.
</Accordion>
</AccordionGroup>
## Troubleshooting
Having issues? Check:
- [How to Fix Import Errors](/user-guide/data-migration/how-tos/fix-import-errors)
- [How to Import Relations](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv)
- [Field Mapping Reference](/user-guide/data-migration/capabilities/field-mapping)

View File

@@ -0,0 +1,168 @@
---
title: Import Data via API
description: When and how to use Twenty's APIs for large-scale data imports.
---
## Overview
Twenty provides both **GraphQL** and **REST APIs** for programmatic data import. Use the API when CSV import isn't practical for your data volume or when you need automated, recurring imports.
## When to Use API Import
| Scenario | Recommended Method |
|----------|-------------------|
| Under 10,000 records | CSV Import |
| 10,000 - 50,000 records | CSV Import (split into files) |
| **50,000+ records** | **API Import** |
| One-time migration | Either (based on volume) |
| **Recurring imports** | **API Import** |
| **Real-time sync** | **API Import** |
| **Integration with other systems** | **API Import** |
<Note>For datasets in the hundreds of thousands, the API is significantly faster and more reliable than multiple CSV imports.</Note>
## API Rate Limits
Twenty enforces rate limits to ensure system stability:
| Limit | Value |
|-------|-------|
| **Requests per minute** | 100 |
| **Records per batch call** | 60 |
| **Maximum throughput** | ~6,000 records/minute |
<Warning>
**Plan your import around these limits.**
For 100,000 records at maximum throughput, expect approximately 17 minutes of import time. Add buffer time for error handling and retries.
</Warning>
## Getting Started
### Step 1: Get Your API Key
1. Go to **Settings → Developers**
2. Click **+ Create API key**
3. Give your key a descriptive name
4. Copy the API key immediately (it won't be shown again)
5. Store it securely
<Warning>
**Keep your API key secret.**
Anyone with your API key can access and modify your workspace data. Never commit it to code repositories or share it publicly.
</Warning>
### Step 2: Choose Your API
Twenty supports two API types:
| API | Best For | Documentation |
|-----|----------|---------------|
| **GraphQL** | Flexible queries, fetching related data, complex operations | [API Docs](/developers/extend/api) |
| **REST** | Simple CRUD operations, familiar REST patterns | [API Docs](/developers/extend/api) |
Both APIs support:
- Creating, reading, updating, and deleting records
- **Batch operations** — create or update up to 60 records per call
**For imports, use batch operations** to maximize throughput within rate limits.
### Step 3: Plan Your Import Order
Just like CSV imports, **order matters** for relations:
1. **Companies** first (no dependencies)
2. **People** second (can link to Companies)
3. **Opportunities** third (can link to Companies and People)
4. **Tasks/Notes** (can link to any of the above)
5. **Custom objects** (following their dependencies)
## Best Practices
### Batch Your Requests
- Don't send records one at a time
- Group up to **60 records per API call**
- This maximizes throughput within rate limits
### Handle Rate Limits
- Implement delays between requests (600ms minimum for sustained imports)
- Use exponential backoff when you hit limits
- Monitor for 429 (Too Many Requests) responses
### Validate Data First
- Clean and validate your data before importing
- Check required fields are populated
- Verify formats match Twenty's requirements (see [Field Mapping](/user-guide/data-migration/capabilities/field-mapping))
### Log Everything
- Log every record imported (including IDs)
- Log errors with full context
- This helps debug issues and verify completion
### Test First
- Test with a small batch (10-20 records)
- Verify data appears correctly in Twenty
- Then run the full import
### Upsert to Avoid Duplicates
The GraphQL API supports **batch upsert** — update if the record exists, create if not. This prevents duplicates when re-running imports.
## Finding Object and Field Names
To see available objects and fields:
1. Go to **Settings → API and Webhooks**
2. Browse the **Metadata API**
3. View all standard and custom objects with their fields
The documentation shows all standard and custom objects, their fields, and the expected data types.
## Professional Services
For complex API migrations, our partners can help:
| Service | What's Included |
|---------|-----------------|
| **Data Model Design** | design your optimal data structure |
| **Migration Scripts** | write and run the import scripts |
| **Data Transformation** | handle complex mapping and cleanup |
| **Validation & QA** | verify the migration is complete |
**Best for:**
- Migrations of 100,000+ records
- Complex data transformations
- Tight timelines
- Teams without developer resources
Contact us at [contact@twenty.com](mailto:contact@twenty.com) or explore our [Implementation Services](/user-guide/getting-started/capabilities/implementation-services).
## FAQ
<AccordionGroup>
<Accordion title="What's the difference between GraphQL and REST?">
GraphQL lets you request exactly the data you need in a single query and is better for complex operations. REST uses standard HTTP methods (GET, POST, PUT, DELETE) and may be more familiar if you've worked with traditional APIs.
</Accordion>
<Accordion title="Can I update existing records via API?">
Yes! Use update mutations (GraphQL) or PUT/PATCH requests (REST) with the record's `id`.
</Accordion>
<Accordion title="How do I handle duplicates?">
Query for existing records first using unique identifiers (email, domain). Update if exists, create if not.
</Accordion>
<Accordion title="Can I delete records via API?">
Yes, use delete mutations (GraphQL) or DELETE requests (REST).
</Accordion>
<Accordion title="Is there a Python or Node.js SDK?">
Not currently, but both APIs work with any HTTP client in any language.
</Accordion>
</AccordionGroup>
## API Documentation
For full implementation details, code examples, and schema reference:
- [API Documentation](/developers/extend/api)

View File

@@ -0,0 +1,218 @@
---
title: Import Relations Between Objects via CSV
description: Complete step-by-step guide to linking records during CSV import.
---
## Overview
This guide walks you through importing relations between objects—for example, linking People to Companies, or Opportunities to People.
<Note>**What can be imported:** Only one-to-many relations pointing to a single object type. Relations pointing to multiple object types (like Notes linking to People AND Companies) are not yet supported for import.</Note>
## Understanding Relations
### What is a "One-to-Many" Relation?
In a one-to-many relation:
- **One** Company has **many** People (employees)
- **One** Company has **many** Opportunities
- **One** Person has **many** Tasks
The "one" side is the **parent**. The "many" side is the **child**.
### Common Relations in Twenty
| Relation | "One" Side (Parent) | "Many" Side (Child) |
|----------|---------------------|---------------------|
| Companies → People | Company | People |
| Companies → Opportunities | Company | Opportunities |
| People → Tasks | Person | Tasks |
| People → Notes | Person | Notes |
## Step 1: Identify the "One" and "Many" Sides
Before importing, determine which object is the parent and which is the child.
**Ask yourself:** "Does ONE [Object A] have MANY [Object B]?"
- One Company → Many People ✓ (Company is parent)
- One Person → Many Companies ✗ (This is wrong—a person belongs to one company)
## Step 2: Import the Parent Records First
The parent ("one" side) must exist in Twenty before you can reference it.
**Import order:**
1. **Companies** first (no dependencies)
2. **People** second (link to Companies)
3. **Opportunities** third (link to Companies and/or People)
4. **Tasks/Notes** (link to any of the above)
<Warning>
**If the parent record doesn't exist, the import will fail.**
Always verify that Companies are imported before importing People with company references.
</Warning>
## Step 3: Note the Parent's Unique Identifier
You need to reference the parent record using a **unique identifier**. Available options:
| Parent Object | Available Unique Identifiers |
|---------------|------------------------------|
| **Companies** | `id` (UUID), `domain` (recommended), or any custom unique field |
| **People** | `id` (UUID), `email`, or any custom unique field |
| **Workspace Members** | `id` (UUID), `email` (not name) |
| **Custom Objects** | `id` (UUID), or any field marked as unique |
<Note>**Recommended:** Use `domain` for Companies and `email` for People. These are human-readable and easy to verify in your spreadsheet.</Note>
### Finding the Identifier
If you need the `id`:
1. Export the parent records from Twenty
2. The export includes the `id` column
3. Use these IDs in your child records file
## Step 4: Verify the Relation Field Exists
Before importing, ensure the relation field exists between your objects.
**To check or create:**
1. Go to **Settings → Data Model**
2. Select your child object (e.g., People)
3. Look for a relation field pointing to the parent (e.g., Company)
4. If it doesn't exist, create it:
- Click **+ Add field**
- Select **Relation** type
- Choose the parent object
## Step 5: Prepare Your CSV File
Add a column to your child CSV that references the parent using its unique identifier.
### Example: People Linking to Companies
**Your People CSV:**
```csv
firstName,lastName,email,jobTitle,companyDomain
John,Smith,john@acme.com,CEO,https://acme.com
Jane,Doe,jane@widgets.co,CTO,https://widgets.co
Bob,Johnson,bob@techstart.io,Developer,https://techstart.io
```
The `companyDomain` column references the Company's domain.
### Format Requirements
| Identifier | Format | Example |
|------------|--------|---------|
| Domain | URL format | `https://acme.com` |
| Email | Standard email | `john@acme.com` |
| ID | UUID | `c776ee49-f608-4a77-8cc8-6fe96ae1e43f` |
<Warning>
**Domain format matters!**
Use `https://domain.com` (not just `domain.com`). This matches how Twenty stores Company domains and prevents matching errors.
</Warning>
### Important Rules
1. **Exact match required** — the value must exactly match the parent record
2. **Map only ONE unique identifier** — don't include both `companyId` AND `companyDomain`
3. **Case sensitive** — `Acme.com` ≠ `acme.com`
## Step 6: Upload and Map the Relation
1. Navigate to the child object (e.g., People)
2. Click **⋮** → **Import records**
3. Upload your CSV file
4. In the field mapping step:
- Find your relation column (e.g., `companyDomain`)
- Map it to the **Company** relation field
5. Complete the remaining mapping
6. Review errors and confirm
Twenty will automatically link each child record to the matching parent.
## Step 7: Verify the Import
After importing:
1. Open a few child records (e.g., People)
2. Verify the relation field shows the correct parent (e.g., Company)
3. Open a parent record and check the related records section
## Common Mistakes to Avoid
| Mistake | Problem | Solution |
|---------|---------|----------|
| **Wrong import order** | Importing People before Companies | Always import parents first, then children |
| **Wrong domain format** | Using `acme.com` instead of `https://acme.com` | Use full URL format with `https://` |
| **Multiple unique fields** | Mapping both `companyId` AND `companyDomain` | Map only ONE unique identifier |
| **Missing relation field** | The relation field doesn't exist in the data model | Create it in **Settings → Data Model** before importing |
| **Non-existent records** | The parent record doesn't exist in Twenty | Import parent records first, or check for typos |
| **Case mismatch** | `Acme.com` in file but `acme.com` in Twenty | Ensure exact case matching |
## Linking to Workspace Members
When linking to Workspace Members (your team):
- Use their **email address**, not their name
- Example: `owner@yourcompany.com`, not "John Smith"
```csv
taskName,assignedTo
Follow up with client,john@yourcompany.com
Review proposal,jane@yourcompany.com
```
## FAQ
<AccordionGroup>
<Accordion title="What if my parent record doesn't have a domain or email?">
You have two options:
1. Use the Twenty `id` (export parent records to get their IDs)
2. Create a custom unique field in your data model to store an external ID from your previous system
</Accordion>
<Accordion title="Can I update relations on existing records?">
Yes! Include the child record's unique identifier (e.g., `email` for People) and the new relation value. The import will update the relation.
</Accordion>
<Accordion title="Can I import Many-to-Many relationships?">
Many-to-Many relations are not yet supported for import. This is planned for H1 2026.
</Accordion>
<Accordion title="Can I link to multiple object types (like Notes to People AND Companies)?">
Relations pointing to multiple object types are not yet supported for import/export. This is on our roadmap.
</Accordion>
<Accordion title="What happens if a parent record doesn't exist?">
The import will show an error for that row. You can either:
- Import the parent record first, then re-import
- Fix the reference value
- Remove the row from import
</Accordion>
<Accordion title="Why is my relation not linking correctly?">
Common causes:
- Wrong format (use `https://domain.com` for domains)
- Case mismatch (check exact spelling)
- Parent doesn't exist (import parents first)
- Mapping multiple identifiers (use only one)
</Accordion>
</AccordionGroup>
<Warning>
**Remember: Soft-deleted records count toward uniqueness.**
If you're getting "not found" errors but the record seems to exist, check Command Menu → See deleted records. The parent may have been soft-deleted.
</Warning>
## Troubleshooting
Having issues? Check:
- [How to Fix Import Errors](/user-guide/data-migration/how-tos/fix-import-errors)
- [Import Relations Capabilities](/user-guide/data-migration/capabilities/import-relations)
- [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints)

View File

@@ -0,0 +1,274 @@
---
title: Migrating from Other CRMs
description: Step-by-step guide to migrate your data from any CRM to Twenty.
---
## Overview
This guide walks you through migrating your data from any CRM to Twenty. The process involves auditing your data, preparing your Twenty workspace, exporting from your current system, and importing into Twenty.
<Note>Views, workflows, and permissions must be recreated manually after migration. Plan time for this configuration work.</Note>
## Step 1: Audit Your Current Data
Migration is an opportunity for a fresh start. Don't bring over clutter.
**What to keep:**
- Active contacts and companies
- Open opportunities and deals
- Important notes and activities
- Custom fields you actually use
**What to leave behind:**
- Outdated contacts (no activity in 2+ years)
- Duplicate records
- Test data
- Unused custom fields
## Step 2: Map Your Data Model
Create a mapping document between your current CRM and Twenty:
| Your CRM | Twenty |
|----------|--------|
| Account / Organization | **Company** |
| Contact / Person | **People** |
| Deal / Opportunity | **Opportunity** |
| Activity | **Task** or **Note** |
| Custom Object | **Custom Object** |
**For each field, document:**
- The source field name
- The target Twenty field
- Any format transformations needed (dates, phone numbers, etc.)
<Note>Keep this mapping document handy during import—you'll reference it when mapping columns.</Note>
## Step 3: Set Up Your Twenty Workspace
Before importing data, prepare your Twenty workspace:
### Create Custom Objects and Fields
1. Go to **Settings → Data Model**
2. Create any custom objects you need
3. Add custom fields to standard and custom objects
4. Configure field settings (unique, required, select options, etc.)
<Warning>
**Fields must exist before import.**
The CSV import creates records, not fields. Create all custom fields in Settings → Data Model before importing.
</Warning>
### Invite Your Team
<Warning>
**Invite users BEFORE importing data.**
If your data includes user references (Account Owner, Assignee, etc.), those users must exist in Twenty before import. Otherwise, those relations cannot be mapped.
</Warning>
1. Go to **Settings → Members**
2. Invite all team members
3. **Wait for everyone to accept** their invitation
4. Verify all users appear in your Members list
## Step 4: Export from Your Current CRM
Export your data from your current CRM:
1. Look for an **Export** function (usually under Settings, Data Management, or Admin)
2. Export to **CSV format** when possible
3. Export each object type separately (Companies, Contacts, Deals, etc.)
4. Include all fields you want to migrate
**Export these objects (in this order for reference):**
1. Companies / Accounts / Organizations
2. Contacts / People
3. Deals / Opportunities
4. Notes and Activities
5. Custom objects
## Step 5: Clean and Format Your Data
Open each exported CSV in a spreadsheet application and prepare it for Twenty.
### Remove Duplicates
1. Sort by the unique field (email for People, domain for Companies)
2. Remove or merge duplicate rows
3. Verify no duplicates exist in Twenty already
### Format Fields Correctly
| Field Type | Required Format |
|------------|-----------------|
| **Domain** | `https://domain.com` |
| **Email** | `name@domain.com` (must be unique) |
| **Date** | `YYYY-MM-DD` |
| **Phone** | Three columns: Number, Country Code, Calling Code |
| **Boolean** | `TRUE` or `FALSE` (uppercase) |
| **Select fields** | Use API names, not display labels |
<Warning>
**Domain format is critical.**
Use `https://domain.com` (not `domain.com` or `www.domain.com`). This matches Twenty's format and prevents duplicates when you connect email/calendar sync.
</Warning>
See [How to Prepare Your CSV Files](/user-guide/data-migration/how-tos/prepare-your-csv-files) for complete formatting requirements for all field types.
### Add Relation Columns
To link records (e.g., People to Companies), add a column with the parent's unique identifier.
**Example: People CSV with Company link**
```csv
firstName,lastName,email,companyDomain
John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
See [How to Import Relations](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for detailed instructions on linking records.
### Update User References
If your data includes user assignments (Owner, Assignee):
1. Add a column with the **user's email** (not just their ID from the old system)
2. Use the same email addresses that users used to join your Twenty workspace
See [How to Prepare Your CSV Files](/user-guide/data-migration/how-tos/prepare-your-csv-files) for complete formatting guide.
## Step 6: Import to Twenty
<Warning>
**Import Order Matters!**
Always import in this order:
1. **Companies** first (no dependencies)
2. **People** second (link to Companies)
3. **Opportunities** third (link to Companies/People)
4. **Notes and Tasks** (link to records)
5. **Custom objects** following their dependencies
The parent record must exist before you can reference it.
</Warning>
### Import Each Object
For each CSV file, in order:
1. Navigate to the object in Twenty
2. Click **⋮ → Import records**
3. Upload the CSV file
4. Map columns to fields:
- Map user email columns to the appropriate relation fields
- Map relation columns (like `companyDomain`) to relation fields
5. Review and fix any errors in the UI
6. Confirm the import
7. Verify a few records before proceeding to the next file
**Detailed guides:**
- [How to Import Companies](/user-guide/data-migration/how-tos/import-companies-via-csv)
- [How to Import Contacts](/user-guide/data-migration/how-tos/import-contacts-via-csv)
- [How to Import Relations](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv)
## Step 7: Large Migrations (50,000+ Records)
For large migrations:
| Volume | Recommended Approach |
|--------|---------------------|
| Under 10,000 records | Single CSV import |
| 10,000 - 50,000 records | Split into multiple CSV files |
| 50,000+ records | Use the API |
**For API imports:**
- Faster and more reliable for large datasets
- Supports batch operations (up to 60 records per call)
- See [How to Import Data via API](/user-guide/data-migration/how-tos/import-data-via-api)
## Step 8: Post-Migration Setup
After importing data, complete your workspace configuration:
### Recreate Views
- Set up saved views with filters, sorts, and column configurations
- Create any kanban or calendar views you need
### Recreate Workflows
- Rebuild your automations in **Settings → Workflows**
- Start with the most critical workflows
- Test each one before relying on it
### Configure Roles and Permissions
- Set up roles in **Settings → Members → Roles**
- Assign users to appropriate roles
### Connect Email and Calendar
- Each user connects their own account in **Settings → Accounts**
- Twenty will start syncing emails to contact records
- See [Email & Calendar](/user-guide/calendar-emails/overview)
### Train Your Team
- Walk through the new interface together
- Document any team-specific processes
## Common Issues and Solutions
| Issue | Cause | Solution |
|-------|-------|----------|
| **Duplicate errors** | Email/domain already exists | Remove duplicates from file, or include unique identifier to update existing records |
| **Relation not found** | Parent record doesn't exist | Import parent objects first (Companies before People) |
| **Missing fields** | Custom field doesn't exist | Create field in Settings → Data Model before importing |
| **Select field errors** | Using display labels | Use API names (enable Advanced mode in Settings to find them) |
| **User relation empty** | User hasn't accepted invite | Ensure all users accept invitations before importing |
See [How to Fix Import Errors](/user-guide/data-migration/how-tos/fix-import-errors) for detailed troubleshooting steps.
## Post-Migration Checklist
### Data Integrity
<Check>All records imported (compare counts with source system)</Check>
<Check>Relations working correctly (People linked to Companies)</Check>
<Check>User assignments mapped correctly (Owner, Assignee)</Check>
<Check>Custom fields populated</Check>
<Check>No unexpected duplicates</Check>
### Configuration
<Check>Views recreated</Check>
<Check>Workflows recreated and tested</Check>
<Check>Roles and permissions configured</Check>
<Check>Email/calendar sync connected</Check>
### Team Readiness
<Check>Team trained on new system</Check>
<Check>Old CRM access plan decided (keep for reference? When to disable?)</Check>
## FAQ
<AccordionGroup>
<Accordion title="Can I migrate workflows automatically?">
Not currently. Workflows must be recreated manually in Twenty.
</Accordion>
<Accordion title="What about file attachments?">
File attachments are not included in CSV exports. You'll need to re-upload them manually, migrate via API, or contact our team for assistance.
</Accordion>
<Accordion title="Can I keep both systems running during migration?">
Yes, we recommend keeping your old CRM running until you've verified the migration is complete. Just be careful not to create new data in both places.
</Accordion>
<Accordion title="How long does migration typically take?">
Depends on data volume and complexity. Small migrations (under 10,000 records) can be done in a few hours. Large migrations may take several days including data cleanup and testing.
</Accordion>
</AccordionGroup>
## Need Help?
<Tip>
Want help with your migration? [Find a certified Twenty partner](https://twenty.com/partners/list?categories=SOLUTIONING&ref=docs-migrate-crm) to move your data, pipelines, and users end-to-end.
</Tip>

View File

@@ -0,0 +1,167 @@
---
title: Migrating from Self-Hosted to Cloud
description: Step-by-step guide to migrate your Twenty self-hosted instance to Twenty Cloud.
---
## Overview
This guide walks you through migrating your data from a Twenty self-hosted instance to Twenty Cloud. The process involves setting up your cloud workspace, exporting your data, and re-importing it.
<Note>Views, workflows, and roles must be recreated manually after migration. Plan time for this configuration work.</Note>
## Step 1: Create Your Cloud Workspace
1. Go to [app.twenty.com](https://app.twenty.com) and create a new workspace
2. Complete the initial setup wizard
3. Note your new workspace URL
## Step 2: Recreate Your Data Model
Before importing data, recreate your custom objects and fields:
1. Go to **Settings → Data Model** in your cloud instance
2. Create custom objects that match your self-hosted setup
3. Add custom fields to standard and custom objects
4. Configure field settings (unique, required, etc.)
<Note>Take screenshots of your self-hosted data model for reference, or keep both instances open side by side.</Note>
## Step 3: Invite All Users
<Warning>
**Critical: Invite users BEFORE importing data.**
Users must accept their invitations before you import any records that reference them (like Account Owner fields). If users don't exist yet, those relations cannot be mapped.
</Warning>
1. Go to **Settings → Members** in your cloud instance
2. Invite all team members who had accounts on self-hosted
3. **Wait for everyone to accept** their invitation
4. Verify all users appear in your Members list
## Step 4: Export Data from Self-Hosted
Export each object from your self-hosted instance:
1. Navigate to each object (Companies, People, Opportunities, etc.)
2. Configure the view to show **all columns** you want to migrate
3. Click **⋮ → Export view**
4. Save each CSV file with a clear name (e.g., `companies-export.csv`)
**Export in this order** (for reference when importing):
1. Companies
2. People
3. Opportunities
4. Custom objects (following their dependencies)
5. Tasks, Notes
## Step 5: Update Workspace Member References
The exported CSVs contain user IDs from your self-hosted instance. These IDs won't match your cloud instance, so you need to replace them with emails.
**For each CSV file with user references (Owner, Assignee, etc.):**
1. Open the CSV in a spreadsheet application
2. Add a new column next to each user ID column (e.g., `accountOwnerEmail` next to `accountOwnerId`)
3. Fill in the **email address** of each user
4. You can delete the old ID column or leave it (it will be skipped during import)
**Example:**
Before:
```csv
name,domain,accountOwnerId
Acme Corp,https://acme.com,old-uuid-123
```
After:
```csv
name,domain,accountOwnerEmail
Acme Corp,https://acme.com,john@yourcompany.com
```
<Note>Use the same email addresses that users used to accept their cloud workspace invitation.</Note>
## Step 6: Plan Your Import Order
Import files in the correct order to maintain relationships:
1. **Companies** first (no dependencies)
2. **People** second (link to Companies)
3. **Opportunities** third (link to Companies and People)
4. **Custom objects** (following their dependencies)
5. **Tasks and Notes** last (link to other records)
See [How to Import Relations](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for details on maintaining relationships.
## Step 7: Import to Cloud
For each CSV file, in order:
1. Navigate to the object in your cloud instance
2. Click **⋮ → Import records**
3. Upload the CSV file
4. Map columns to fields:
- Map user email columns to the appropriate relation fields
- Map other columns as usual
5. Review and fix any errors
6. Confirm the import
7. Verify a few records before proceeding to the next file
## Step 8: Recreate Configuration
After importing data, manually recreate:
### Views
- Recreate saved views with filters, sorts, and column configurations
- Set up any kanban or calendar views
### Workflows
- Recreate automations in **Settings → Workflows**
- Test each workflow before relying on it
### Roles and Permissions
- Configure roles in **Settings → Members → Roles**
- Assign users to appropriate roles
### Integrations
- Reconnect email and calendar sync for each user
- Reconfigure any API integrations with new API keys
## Post-Migration Checklist
<Check>All data imported successfully</Check>
<Check>Relations between objects working correctly</Check>
<Check>User assignments (Owner, Assignee) mapped correctly</Check>
<Check>Views recreated</Check>
<Check>Workflows recreated and tested</Check>
<Check>Roles and permissions configured</Check>
<Check>Email/calendar sync reconnected</Check>
<Check>API integrations updated with new keys</Check>
## FAQ
<AccordionGroup>
<Accordion title="Can I migrate workflows automatically?">
Not currently. Workflows must be recreated manually in your cloud instance.
</Accordion>
<Accordion title="What about file attachments and images?">
File attachments are not included in CSV exports. You'll need to re-upload any attachments manually, migrate them via API or contact our team for assistance with large migrations.
</Accordion>
<Accordion title="Can I keep both instances running during migration?">
Yes, we recommend keeping your self-hosted instance running until you've verified the cloud migration is complete. Just be careful not to create new data in both places.
</Accordion>
<Accordion title="What if a user hasn't accepted their invitation yet?">
Records referencing that user will fail to import or the relation will be empty. Ensure all users accept invitations before importing data.
</Accordion>
</AccordionGroup>
## Need Help?
<Tip>
Migrating a large or complex workspace? [Get a certified Twenty partner](https://twenty.com/partners/list?categories=HOSTING&ref=docs-migrate-cloud) to handle the move end-to-end. *(Or loop in our team: [contact@twenty.com](mailto:contact@twenty.com).)*
</Tip>

View File

@@ -0,0 +1,237 @@
---
title: Prepare Your CSV Files
description: Complete step-by-step guide to format your data for import into Twenty.
---
## Overview
This guide walks you through preparing your CSV file for a successful import. Follow these steps in order to avoid errors.
## Step 1: Check File Requirements
Before you start, ensure your file meets these requirements:
| Requirement | Details |
|-------------|---------|
| **Format** | CSV, XLSX, or XLS |
| **Size limit** | 10,000 records per file |
| **Encoding** | UTF-8 recommended |
| **Structure** | One object type per file |
<Note>For datasets larger than 10,000 records, split into multiple files or use the [API import](/user-guide/data-migration/how-tos/import-data-via-api).</Note>
## Step 2: Download the Sample File
**This is the most important step.** The sample file shows you the exact column names and format Twenty expects.
1. Go to the object view (People, Companies, etc.)
2. Click **⋮** → **Import records**
3. Click **Download sample file**
4. Use this file as your template
<Note>**Pro tip:** Export a few existing records instead. This gives you real examples of how data should be formatted, and the column names will map automatically during import.</Note>
## Step 3: Remove Duplicate Values
Twenty enforces uniqueness on certain fields. Duplicates will cause import errors.
| Object | Unique Fields |
|--------|---------------|
| **People** | `id`, `email` |
| **Companies** | `id`, `domain` |
| **Custom objects** | `id`, plus any field you marked as unique |
**Before importing:**
1. Sort your spreadsheet by the unique field (email or domain)
2. Remove or merge duplicate rows
3. Check for duplicates that already exist in Twenty
<Warning>**Soft-deleted records count toward uniqueness.** Records in Command Menu → See deleted records will cause duplicate errors. Delete them permanently or restore and update them.</Warning>
## Step 4: Format Each Field Type Correctly
Different field types require specific formats. Here's the complete reference:
### Text Fields
- No special formatting required
- Leading/trailing spaces are automatically trimmed
### Email Fields
- Must be valid email format: `name@domain.com`
- Must be unique (no duplicates in file or in Twenty)
- For additional emails, use this format in the **Emails / Additional Emails** column:
```
["jane@twenty.com","jane.doe@twenty.com"]
```
### Domain Fields
- **Recommended format**: `https://domain.com`
- This matches the format used by mailbox/calendar sync (prevents duplicates)
- Fill both columns:
- **Domain / Domain Label**: `domain.com`
- **Domain / Domain URL**: `https://domain.com`
- Must be unique within your file and in Twenty
### Phone Fields
Phone is a **nested field** requiring multiple columns:
| Column | Example |
|--------|---------|
| **Phones / Primary Phone Number** | `4159095555` |
| **Phones / Primary Phone Country Code** | `US` |
| **Phones / Primary Phone Calling Code** | `+1` |
### Address Fields
Address is a **nested field** with multiple columns (some can be left empty):
- **Address / Address 1**: Street address line 1
- **Address / Address 2**: Street address line 2 (optional)
- **Address / City**: City name
- **Address / State**: State or province
- **Address / Country**: Country name
- **Address / Post Code**: Postal/ZIP code
### Date Fields
Use consistent formatting throughout your file:
- `YYYY-MM-DD` (recommended): `2024-03-15`
- ISO 8601: `2024-03-15T10:30:00Z`
### Number Fields
- Numbers only (no text)
- Use period for decimals: `1234.56`
- No thousands separators (not `1,234.56`)
### Currency Fields
Currency is a **nested field** requiring two columns that **both must be filled**:
| Column | Example |
|--------|---------|
| **Amount / Amount** | `1234.56` |
| **Amount / Currency** | `USD` |
### Boolean Fields
Use uppercase: `TRUE` or `FALSE`
<Warning>Lowercase `true` or `false` will not work.</Warning>
### Select Fields
Use the **API name** of the option, not the display label.
**How to find API names:**
1. Go to **Settings → Data Model**
2. Select the object and field
3. Enable **Advanced mode** (toggle at bottom right)
4. Copy the API name (e.g., `OPTION_1`, not "Option 1")
<Note>New select options are not created automatically. Add them in **Settings → Data Model** before importing.</Note>
### Multi-Select Fields
Use API names in array format:
```
["VALUE1","VALUE2"]
```
### Array Fields
Use JSON array format:
```
["value1","value2"]
```
### Rating Fields
Use the format: `RATING_1`, `RATING_2`, `RATING_3`, `RATING_4`, or `RATING_5`
### Links/URL Fields
Fill both columns:
- **Links / Link Label**: `Twenty`
- **Links / Link URL**: `https://twenty.com`
For secondary links, use the **Links / Secondary Links** column:
```
[{"url":"https://twenty.com","label":"Twenty"}]
```
### JSON Fields
Use valid JSON format:
```
{"key":"value","key2":"value2"}
```
### ID Fields
- **Optional**: Twenty auto-generates IDs if not provided
- **Format**: UUID (e.g., `c776ee49-f608-4a77-8cc8-6fe96ae1e43f`)
- **Use case**: Include ID to update existing records instead of creating new ones
## Step 5: Add Relation Columns (If Linking Records)
To link records to other objects (e.g., People to Companies), add a column with the unique identifier of the related record.
**Example**: Linking People to Companies
Add a column to your People CSV:
```
firstName,lastName,email,companyDomain
John,Smith,john@acme.com,https://acme.com
Jane,Doe,jane@widgets.co,https://widgets.co
```
**Important rules for relations:**
- The parent record must already exist in Twenty
- Use the **Domain URL** format (`https://domain.com`), not the label
- Map only ONE unique identifier (don't include both `companyId` AND `companyDomain`)
- For Workspace Members, use their **email** (not name)
<Warning>
**Import Order Matters!**
Import the "one" side before the "many" side:
1. **Companies** first
2. **People** second (with company reference)
3. **Opportunities** third
The parent record must exist before you can reference it.
</Warning>
See [How to Import Relations](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for detailed instructions.
## Step 6: Ensure Fields Exist in Twenty
The import creates **records**, not **fields**. All fields you want to import must already exist in your data model.
**Before importing:**
1. Go to **Settings → Data Model**
2. Select your object
3. Create any custom fields you need
4. Note the exact field names (they must match your column headers)
## Step 7: Final Checklist
Before uploading your file, verify:
<Check>File is CSV, XLSX, or XLS format</Check>
<Check>File has fewer than 10,000 records</Check>
<Check>Encoding is UTF-8</Check>
<Check>No duplicate emails (for People) or domains (for Companies)</Check>
<Check>Dates use consistent format throughout</Check>
<Check>Domains use `https://domain.com` format</Check>
<Check>Boolean fields use `TRUE` or `FALSE` (uppercase)</Check>
<Check>Select fields use API names, not display labels</Check>
<Check>All custom fields exist in Settings → Data Model</Check>
<Check>Parent records imported before child records</Check>
<Check>Relation columns reference existing records</Check>
## Common Mistakes to Avoid
| Mistake | Solution |
|---------|----------|
| Using `true` instead of `TRUE` | Boolean values must be uppercase |
| Using display labels for Select fields | Find and use API names in Settings |
| Importing People before Companies | Always import parent objects first |
| Missing currency code for Currency fields | Fill both Amount and Currency columns |
| Wrong domain format | Use `https://domain.com` consistently |
| Mapping multiple unique fields for relations | Map only ONE (domain OR id, not both) |
## Next Steps
Your file is ready! Now:
- [Import Companies](/user-guide/data-migration/how-tos/import-companies-via-csv) (import these first)
- [Import Contacts](/user-guide/data-migration/how-tos/import-contacts-via-csv)
- [Fix any import errors](/user-guide/data-migration/how-tos/fix-import-errors)

View File

@@ -0,0 +1,195 @@
---
title: Update Existing Records via Import
description: Complete step-by-step guide to bulk updating records using CSV import.
---
## Overview
Need to update many records at once? Instead of editing them one by one, use the CSV import to bulk update existing records.
**Use cases:**
- Update job titles for multiple people
- Change company information in bulk
- Add data to new custom fields
- Correct data errors across many records
## How It Works
When you import a file containing a **unique identifier** that matches an existing record, Twenty updates that record instead of creating a duplicate.
| If unique identifier... | Twenty will... |
|-------------------------|----------------|
| Matches an existing record | **Update** the existing record |
| Doesn't match any record | **Create** a new record |
| Is missing from your file | **Create** a new record (with auto-generated ID) |
<Warning>
**Multi-Select fields are overwritten, not merged.**
If a record has `Option A` and `Option B` selected, and you import `["Option C"]`, the record will only have `Option C` after import. The import replaces all previous selections—it does not add to them.
To keep existing values, include them all in your import: `["Option A","Option B","Option C"]`
</Warning>
## Step 1: Export Your Current Data
First, export the records you want to update:
1. Navigate to the object (People, Companies, etc.)
2. **Add the columns you need** — click **Options → Fields** to show the fields you want to update
3. **Filter if needed** — narrow down to only the records you want to update
4. Click **⋮** → **Export view**
5. Save the CSV file
<Note>**Why export first?** The exported file has the correct format, includes unique identifiers, and maps automatically during import.</Note>
### What Gets Exported
- All visible columns in your current view
- The record's unique identifiers (`id`, `email`, `domain`)
- Current field values you can modify
## Step 2: Edit the CSV File
Open the exported file in your spreadsheet application (Excel, Google Sheets, etc.):
1. **Keep the unique identifier column** — don't delete `id`, `email`, or `domain`
2. **Update the values** in the columns you want to change
3. **Remove columns you don't need to update** (optional, but cleaner)
4. **Don't change unique identifier values** — or Twenty will create new records
### Example: Updating Job Titles
**Exported file:**
```csv
id,email,firstName,lastName,jobTitle
550e8400-e29b-41d4-a716-446655440001,john@acme.com,John,Smith,Sales Rep
550e8400-e29b-41d4-a716-446655440002,jane@acme.com,Jane,Doe,Sales Rep
550e8400-e29b-41d4-a716-446655440003,bob@acme.com,Bob,Johnson,Sales Rep
```
**After your edits:**
```csv
id,email,firstName,lastName,jobTitle
550e8400-e29b-41d4-a716-446655440001,john@acme.com,John,Smith,Account Executive
550e8400-e29b-41d4-a716-446655440002,jane@acme.com,Jane,Doe,Senior Account Executive
550e8400-e29b-41d4-a716-446655440003,bob@acme.com,Bob,Johnson,Account Executive
```
<Warning>
**Don't change the unique identifier values.**
If you change `john@acme.com` to `john.smith@acme.com`, Twenty will create a new record instead of updating the existing one.
</Warning>
## Step 3: Import the Updated File
1. Navigate to the object
2. Click **⋮** → **Import records**
3. Upload your edited CSV file
4. **Ensure the unique identifier is mapped** — verify `email`, `domain`, or `id` is mapped correctly
5. Review the field mappings
6. Check for errors
7. Click **Confirm**
Twenty matches records by the unique identifier and updates them with new values.
## Choosing the Right Unique Identifier
| Object | Recommended | Alternative | Notes |
|--------|-------------|-------------|-------|
| **People** | `email` | `id` | Email is human-readable |
| **Companies** | `domain` | `id` | Domain is human-readable |
| **Custom objects** | Any unique field | `id` | Use your custom unique field |
<Note>**Use only ONE unique identifier.** Don't map both `email` AND `id`. This can cause confusion and errors.</Note>
### Using Custom Unique Fields
If you have a custom field marked as unique (like an external ID from another system):
1. Include that field in your export and import
2. Map it during import
3. Twenty will match on that field
## Step 4: Verify the Updates
After importing:
1. Open a few updated records
2. Verify the changes were applied
3. Check that no duplicate records were created
## What About Fields Not in Your File?
**Fields not included in your import file remain unchanged.**
| Your file includes... | Result |
|-----------------------|--------|
| `email`, `jobTitle` | Only `jobTitle` is updated; other fields stay the same |
| `email`, `jobTitle`, `phone` | `jobTitle` and `phone` are updated |
This means you only need to include the fields you want to change (plus the unique identifier).
## Combining Updates and New Records
You can update existing records AND create new ones in the same import:
```csv
email,firstName,lastName,jobTitle
john@acme.com,John,Smith,Senior Manager ← Updates existing (email matches)
newperson@acme.com,New,Person,Analyst ← Creates new (email doesn't match)
```
## Common Mistakes to Avoid
| Mistake | Problem | Result | Solution |
|---------|---------|--------|----------|
| **Changing unique identifier** | Changed `john@acme.com` to `john.smith@acme.com` | Creates new record instead of updating | Keep unique identifiers unchanged |
| **Multiple unique fields** | Mapping both `email` AND `id` | Potential matching conflicts | Map only ONE unique identifier |
| **No unique identifier** | File only has `firstName`, `lastName`, `jobTitle` | All rows create new records | Always include `email`, `domain`, or `id` |
| **Case mismatch** | File has `John@acme.com` but Twenty has `john@acme.com` | Creates new record | Export from Twenty to get exact values |
## FAQ
<AccordionGroup>
<Accordion title="What if some records don't exist yet?">
Records with unique identifiers that don't match existing records will be created as new records. This lets you update and create in the same import.
</Accordion>
<Accordion title="Can I clear/empty a field value?">
Yes, leave the cell empty in your CSV. The import will clear that field's value on the existing record.
</Accordion>
<Accordion title="What happens to fields I don't include in the import?">
Fields not in your import file remain unchanged on existing records. Only fields you include are updated.
</Accordion>
<Accordion title="Can I update relation fields (like Company)?">
Yes! Include the relation's unique identifier (e.g., `companyDomain`) and map it to the relation field. The relation will be updated.
</Accordion>
<Accordion title="How do I know which records will be updated vs. created?">
During the import review step, Twenty shows you how many records will be updated vs. created based on unique identifier matches.
</Accordion>
<Accordion title="Can I undo a bulk update?">
There's no automatic undo. We recommend exporting your data as a backup before making bulk updates.
</Accordion>
</AccordionGroup>
## Best Practices
1. **Export first** — always start from an export to ensure correct format
2. **Backup before updating** — export your data before making bulk changes
3. **Test with a few records** — try updating 5-10 records first before doing a large batch
4. **Use human-readable identifiers** — `email` and `domain` are easier to verify than `id`
5. **Only include necessary columns** — fewer columns means less chance for errors
## Troubleshooting
Having issues? Check:
- [How to Fix Import Errors](/user-guide/data-migration/how-tos/fix-import-errors)
- [Uniqueness Constraints](/user-guide/data-migration/capabilities/uniqueness-constraints)
- [Field Mapping Reference](/user-guide/data-migration/capabilities/field-mapping)

View File

@@ -0,0 +1,79 @@
---
title: Data Migration
description: Import and export your CRM data via CSV files or API.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## Import Methods
Twenty supports two main methods for importing data:
| Method | Best For | Volume Limit |
|--------|----------|--------------|
| **CSV Import** | Standard migrations, regular updates | 10,000 records per file |
| **API Import** | Large-scale migrations, automation | Unlimited |
<Note>For very large datasets (hundreds of thousands of records), use the API. Our [implementation partners](/user-guide/getting-started/capabilities/implementation-services) can help run these scripts if needed.</Note>
## CSV Import Basics
You can import data for any object using CSV, XLSX, or XLS files. Each file should contain **only one type of object** (e.g., only People records).
<Note>**Fields must exist before import.** Uploading a CSV creates records but does not create fields. If you need custom fields, create them first under **Settings → Data Model**.</Note>
### Steps
1. Navigate to the object where you want to import data
2. Click the **⋮** icon on the top right (this is the Command Menu) and click on **Import records**
3. Download the template file to ensure your data is in the expected format
4. Upload your formatted CSV file
5. Map your columns to Twenty fields
6. Review errors (highlighted in yellow) and fix them, directly editing in the UI
7. Confirm the import
### Importing Relations Between Objects
You can import relations between objects using the CSV import function. You need to reference the related object using a unique field from this object: the `id`, the `email` for People and Workspace Members, the `domain` for companies, any other field set as unique in the data model for any other object.
<Note>**Deleted records count toward uniqueness.** Soft-deleted records (visible under Command Menu → See deleted records) are included in uniqueness checks. If you import a record with the same unique value as a deleted record, the deleted record will be restored.</Note>
<Warning>
**Import Order Matters!**
When importing related objects, upload files in this order:
1. **Companies** first (the "one" side of relationships)
2. **People** second (linked to Companies via companyId)
3. **Opportunities** third (linked to Companies/People)
4. **Custom objects** with relations last
Why? The "one" side of a one-to-many relationship must exist before you can reference it. For example, the Company record must exist before you import a Person with that company's ID.
</Warning>
Please refer to [this article](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv) for a step-by-step guide on how to proceed.
## Export Data
Export your workspace data for backups, reporting, or migration.
### Steps
1. Navigate to the object you want to export
2. Configure the view with the columns you need
3. Click **⋮** → **Export view**
4. Save the CSV file
<Note>**Only visible columns are exported.** The CSV file will only contain the columns displayed in your current view. Add or hide columns before exporting to control what data is included.</Note>
<Note>**Export limits**: Up to 20,000 records per export.</Note>
## Permissions
Data import and export require specific permissions:
- **Import**: Requires "Import CSV" permission
- **Export**: Requires "Export CSV" permission
Contact your workspace admin if you don't have these permissions.
## Next Steps
- [Prepare your CSV files](/user-guide/data-migration/how-tos/prepare-your-csv-files)
- [Import relations between objects](/user-guide/data-migration/how-tos/import-relations-between-objects-via-csv)
- [Import via API for large datasets](/user-guide/data-migration/how-tos/import-data-via-api)