Loading...
Loading...
Migrate data from Notion, Confluence, Google Drive, Airtable, Marvin, Condens, EnjoyHQ, Productboard, or local files into Dovetail using the dt CLI.
npx skill4agent add dovetail/skills migrate-to-dovetaildtdtnpm install -g @heydovetail/dtdt initDOVETAIL_API_KEYinstall → init → source add → validate → preview → [user approves] → migrate run# 1. Connect a source
dt source add <source>
# 2. Test connectivity
dt source validate <source>
# 3. Preview what will be imported
dt migrate run --source <source> --preview
# 4. [Wait for user approval]
# 5. Run the import
dt migrate run --source <source>dt.json{
"dovetail": {
"api_key": "your-api-key",
"base_url": "https://mycompany.dovetail.com"
},
"sources": {
"<source>": {
"<option-key>": "<value>"
}
},
"migrations": [
{
"source": "<source>",
"content": ["<url-id-or-type>"],
"destination": {
"type": "data",
"parent": {
"type": "project",
"name": "Destination Project Name"
}
},
"options": {}
}
]
}contentdestination.type"data""doc"destination.parent.type"project""folder"optionsexport NOTION_TOKEN="ntn_xxxxxxxxxxxx"
dt source add notion
dt source validate notion
dt migrate run --source notion --preview
# wait for approval
dt migrate run --source notiondt.json{
"sources": {
"notion": {
"token": "ntn_xxxxxxxxxxxx"
}
},
"migrations": [
{
"source": "notion",
"content": ["notion-database-id-here"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Customer Research" }
}
}
]
}export CONFLUENCE_API_TOKEN="your-api-token"
dt source add confluence
dt source validate confluence
dt migrate run --source confluence --preview
# wait for approval
dt migrate run --source confluencedt.json{
"sources": {
"confluence": {
"base_url": "https://mycompany.atlassian.net/wiki",
"email": "you@company.com",
"token": ""
}
},
"migrations": [
{
"source": "confluence",
"content": ["PROD"],
"destination": {
"type": "doc",
"parent": { "type": "project", "name": "Product Knowledge Base" }
}
}
]
}content"PROD"# Service account only:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"
dt source add gdrive
dt source validate gdrive
dt migrate run --source gdrive --preview
# wait for approval
dt migrate run --source gdrivedt.json{
"sources": {
"gdrive": {
"credentials_file": "/path/to/key.json",
"recursive": "true",
"include_binary": "true"
}
},
"migrations": [
{
"source": "gdrive",
"content": ["1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "UX Research Archive" }
}
}
]
}contentdata.records:readschema.bases:readexport AIRTABLE_TOKEN="your-token"
dt source add airtable
dt source validate airtable
dt migrate run --source airtable --preview
# wait for approval
dt migrate run --source airtabledt.json{
"sources": {
"airtable": {
"token": ""
}
},
"migrations": [
{
"source": "airtable",
"content": ["https://airtable.com/appXXXXXXXXXXXXXX/tblXXXXXXXXXXXXXX"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "User Interview Tracker" }
}
}
]
}content/marvin-downloadmarvin-export/
Project Name/
files/
Interview 1.mp4
insights/
My Report/
content.md
metadata.jsondt source add marvin
dt migrate run --source marvin --preview
# wait for approval
dt migrate run --source marvindt.json{
"migrations": [
{
"source": "marvin",
"content": ["./marvin-export/Customer Interviews"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Customer Interviews" }
},
"options": { "types": "files" }
},
{
"source": "marvin",
"content": ["./marvin-export/Customer Interviews"],
"destination": {
"type": "doc",
"parent": { "type": "project", "name": "Customer Interviews" }
},
"options": { "types": "insights" }
}
]
}contentoptions.types"files""insights".zipdt source add condens
dt migrate run --source condens --preview
# wait for approval
dt migrate run --source condensdt.json{
"migrations": [
{
"source": "condens",
"content": ["/path/to/Onboarding Research.abc123.zip"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Onboarding Research" }
}
}
]
}contentexport ENJOYHQ_API_TOKEN="your-token"
dt source add enjoyhq
dt source validate enjoyhq
dt migrate run --source enjoyhq --preview
# wait for approval
dt migrate run --source enjoyhqexport PRODUCTBOARD_API_TOKEN="your-token"
dt source add productboard
dt source validate productboard
dt migrate run --source productboard --preview
# wait for approval
dt migrate run --source productboarddt.json{
"sources": {
"productboard": {
"token": ""
}
},
"migrations": [
{
"source": "productboard",
"content": ["notes"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Productboard Notes" }
}
},
{
"source": "productboard",
"content": ["features"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Productboard Features" }
}
}
]
}content"notes""features".md.txt.htmldt source add local
dt migrate run --source local --preview
# wait for approval
dt migrate run --source localdt.json{
"migrations": [
{
"source": "local",
"content": ["/path/to/your/folder"],
"destination": {
"type": "data",
"parent": { "type": "project", "name": "Research Files" }
},
"options": { "extensions": ".md,.pdf,.mp4" }
}
]
}contentoptions.extensions| Flag | Description |
|---|---|
| Show what would be migrated without fetching |
| Fetch and transform but skip upload |
| Re-run without creating duplicates |
| Process at most N records per migration |
| Filter by title |
| Filter by creation date |
| Filter by update date |
| Detailed per-record progress logs |
| Run only migrations for source X |
--project--type | | | Description |
|---|---|---|---|
| | | Data (recordings, transcripts, files) inside a project |
| | | Docs inside a project |
| | | Docs directly in a folder |
dt.jsondt migrate run # run everything
dt migrate run --source notion # run one source only| Problem | Fix |
|---|---|
| "no records fetched" | Check source access: Notion database shared with integration, Drive folder shared with service account, correct Confluence space key, valid Airtable token scopes |
| "403 Forbidden" | Dovetail API key may lack permissions, or source account doesn't have read access |
| "401 Unauthorized" | API key or token is invalid or expired |
| Rate limited | Automatic — the CLI retries with exponential backoff |
| Migration interrupted | Run |
| Migration seems stuck | Run |
dt doctor