This project provides tools to export JIRA tasks and import them into ClickUp through their REST API.
- Parse JIRA XML exports
- Convert task data to ClickUp format
- Import tasks with descriptions, comments, priorities, and tags
- Download and upload attachments from JIRA to ClickUp
- Resolve user names in comments (shows actual names instead of account IDs)
- Support for dry-run mode to preview imports
- Rate limiting to respect ClickUp API limits
- Comprehensive error handling and logging
pip install -r requirements.txt- Go to ClickUp and click on your avatar
- Select "Apps" from the dropdown
- Click "Generate" next to "API Token"
- Copy the generated token
- Open the ClickUp list where you want to import tasks
- The List ID is in the URL:
https://app.clickup.com/{team_id}/v/li/{list_id} - Copy the
list_idpart
- Go to your Atlassian account: https://id.atlassian.com/manage-profile/security/api-tokens
- Click "Create API token"
- Give it a descriptive name (e.g., "ClickUp Import")
- Copy the generated token
Note: Without JIRA configuration, the script will still import tasks but skip attachments.
Create a .env file in the project root to store your configuration:
# Copy the template
cp env.example .envEdit the .env file with your actual values:
# ClickUp API Configuration
CLICKUP_API_TOKEN=your_actual_api_token_here
CLICKUP_LIST_ID=your_actual_list_id_here
# JIRA Configuration (for attachment downloads)
JIRA_BASE_URL=https://your-domain.atlassian.net/
JIRA_API_TOKEN=your_jira_api_token_here
JIRA_EMAIL=your.email@example.com
# Optional: Default XML file path
JIRA_XML_FILE=sisr-export.xmlBenefits of using .env file:
- No need to pass API token and list ID as command line arguments
- Keeps sensitive data out of command history
- Easier to manage multiple configurations
- More secure than hardcoding values
If you've set up your .env file, you can run the importer with minimal commands:
# Dry run (preview what would be imported)
python jira_to_clickup.py --dry-run
# Actual import
python jira_to_clickup.py
# Use a different XML file
python jira_to_clickup.py path/to/other-export.xml --dry-run
# Enable verbose debug output
python jira_to_clickup.py --dry-run --verbose
# List available custom fields
python jira_to_clickup.py --list-custom-fieldsYou can still use command line arguments if preferred:
# Dry run (preview what would be imported)
python jira_to_clickup.py sisr-export.xml --api-token YOUR_API_TOKEN --list-id YOUR_LIST_ID --dry-run
# Actual import
python jira_to_clickup.py sisr-export.xml --api-token YOUR_API_TOKEN --list-id YOUR_LIST_IDNote: Command line arguments override environment variables if both are provided.
| Option | Short | Description |
|---|---|---|
--dry-run |
Show what would be imported without actually creating tasks | |
--verbose |
-v |
Enable detailed debugging output for troubleshooting |
--list-custom-fields |
List all custom fields in the ClickUp list (helps find field IDs) | |
--api-token |
ClickUp API token (overrides environment variable) | |
--list-id |
ClickUp List ID (overrides environment variable) |
Use --verbose or -v to enable detailed debugging output. This is helpful for:
- Troubleshooting import issues
- Understanding API responses
- Monitoring task creation progress
- Debugging custom field mappings
# Verbose dry run
python jira_to_clickup.py --dry-run --verbose
# Verbose actual import
python jira_to_clickup.py --verboseNote: Without verbose mode, only essential progress information is shown for cleaner output.
import os
from dotenv import load_dotenv
from jira_to_clickup import JiraToClickUpImporter
# Load environment variables
load_dotenv()
# Get configuration from environment
api_token = os.getenv('CLICKUP_API_TOKEN')
list_id = os.getenv('CLICKUP_LIST_ID')
xml_file = os.getenv('JIRA_XML_FILE', 'sisr-export.xml')
# Initialize importer
importer = JiraToClickUpImporter(api_token, list_id)
# Initialize importer with verbose debug output
# importer = JiraToClickUpImporter(api_token, list_id, verbose=True)
# Parse JIRA XML
tasks = importer.parse_jira_xml(xml_file)
# Import tasks (dry run first)
importer.import_tasks(tasks, dry_run=True)
importer.import_tasks(tasks, dry_run=False)from jira_to_clickup import JiraToClickUpImporter
# Initialize importer with direct values
importer = JiraToClickUpImporter("your_api_token", "your_list_id")
# Initialize importer with verbose debug output
# importer = JiraToClickUpImporter("your_api_token", "your_list_id", verbose=True)
# Parse JIRA XML
tasks = importer.parse_jira_xml("sisr-export.xml")
# Import tasks (dry run first)
importer.import_tasks(tasks, dry_run=True)
importer.import_tasks(tasks, dry_run=False)| JIRA Field | ClickUp Field | Notes |
|---|---|---|
| Summary | Task Name | Prefixed with JIRA key |
| Description + Comments | Task Description | Combined with markdown formatting |
| Priority | Priority | Mapped to ClickUp priority levels (1-4) |
| Status | Tags | Added as status tag |
| Project Key | Tags | Added as project tag |
| Assignee | Tags | Added as assignee tag |
| Due Date | Due Date | Converted to Unix timestamp |
| JIRA Priority | ClickUp Priority |
|---|---|
| Highest | 1 (Urgent) |
| High | 2 (High) |
| Medium | 3 (Normal) |
| Low | 4 (Low) |
| Lowest | 4 (Low) |
The script provides detailed progress information including:
- Number of tasks found and processed
- Success/failure status for each task
- Created ClickUp task IDs
- Summary of successful and failed imports
The script includes built-in rate limiting to respect ClickUp API limits:
- 1 second delay between task creations
- 0.5 second delay between comment additions
- Comprehensive error messages for API failures
- Graceful handling of malformed XML data
- Detailed logging of failed imports with reasons
jira_to_clickup.py- Main importer scriptjira_to_excel.py- Original JIRA to Excel converterexample_import.py- Example usage scriptrequirements.txt- Python dependenciessisr-export.xml- JIRA XML export file
-
Invalid API Token
- Verify your ClickUp API token is correct
- Ensure the token has proper permissions
-
Invalid List ID
- Check that the List ID is correct
- Ensure you have access to the target list
-
Rate Limiting
- If you encounter rate limit errors, the script will show detailed error messages
- Consider reducing the number of tasks imported at once
-
XML Parsing Errors
- Ensure the XML file is a valid JIRA export
- Check that the file is not corrupted
For detailed debugging, you can modify the script to enable verbose logging:
import logging
logging.basicConfig(level=logging.DEBUG)- Never commit API tokens to version control
- Always use
.envfile for sensitive data - the.envfile is automatically ignored by git - The
env.exampletemplate file can be safely committed as it contains no actual credentials - Environment variables are the preferred method for configuration in production environments
- If using manual environment variables, set them in your shell:
export CLICKUP_API_TOKEN="your_token_here"
export CLICKUP_LIST_ID="your_list_id_here"This project is provided as-is for educational and utility purposes.