Backup and restore individual Jira Cloud projects via REST API
Project description
Jira Project Backup & Restore
Backup and restore individual Jira Cloud projects via REST API — issues, comments, worklogs, attachments, boards, and sprints. Fully resumable, with an interactive menu and CLI mode.
Why?
Jira Cloud has no built-in per-project backup/restore. The only native option was the full-instance Backup Manager, which Atlassian deprecated in March 2026. This tool fills the gap using standard REST API v3 endpoints.
Features
| Feature | Description |
|---|---|
| Full project backup | Metadata, components, versions, roles, issues (all fields + changelog), worklogs, attachments, agile boards, sprints |
| 5-phase restore | Issues (epics first, subtasks last), links, comments, worklogs, attachments |
| Multi-project | Backup dozens of projects in a single run |
| Skip existing | --skip-existing skips projects that already have a complete backup |
| Auto-cleanup | Incomplete/partial backup folders are automatically removed before each run |
| Resumable | Safely re-run after interruption — already-processed items are skipped |
| Memory efficient | Issues stream directly to disk — backup 18 000+ issues on a 1 GB host without OOM |
| Dry-run mode | Preview all restore actions without making any API calls |
| Rate-limit aware | Exponential backoff with 429 / Retry-After detection |
| CSV export | Export backup data to CSV files for reporting, auditing, and sharing |
| Backup inspection | Detailed breakdown of issue types, statuses, priorities, and assignees |
| Connection test | Pre-flight check: authentication, project access, and server info |
| Interactive menu | Guided workflow with organised sections and post-operation summaries |
| CLI mode | --backup / --restore / --export-csv flags for scripted or cron use |
Quick Start
1. Install
Via PyPI (recommended):
pip install jira-project-backup-restore
Or clone for development:
git clone https://github.com/davidmalko87/jira-project-backup-restore.git
cd jira-project-backup-restore
pip install -r requirements.txt
2. Configure
cp .env.example .env
Edit .env with your Jira Cloud credentials:
JIRA_URL=https://your-domain.atlassian.net
JIRA_EMAIL=you@example.com
JIRA_API_TOKEN=your-api-token
Generate an API token at id.atlassian.com/manage-api-tokens
3. Run
Interactive menu:
python main.py
==================================================
Jira Backup & Restore Tool v1.3.2
==================================================
Instance : https://your-domain.atlassian.net
Auth : API Token
Backups : ./backups
--- Backup & Restore ---
1) Backup project(s)
2) Restore project from backup
--- Browse & Analyze ---
3) List existing backups
4) Validate backup integrity
5) Upload attachments only
6) Export backup to CSV
7) Inspect backup details
--- Settings & Tools ---
8) Test Jira connection
9) Show current configuration
10) Cleanup incomplete backups
0) Exit
CLI — backup:
python main.py --backup PROJ
python main.py --backup PROJ1,PROJ2
python main.py --backup PROJ1,PROJ2 --skip-existing
CLI — restore:
python main.py --restore backups/PROJ_20260322_143000 --target NEWPROJ
python main.py --restore backups/PROJ_20260322_143000 --target NEWPROJ --dry-run
CLI — export to CSV:
python main.py --export-csv backups/PROJ_20260322_143000
python main.py --export-csv backups/PROJ_20260322_143000 --output-dir /tmp/report
What Gets Backed Up
| File | Contents |
|---|---|
project_meta.json |
Project config — name, lead, category, permission scheme |
components.json |
All project components |
versions.json |
All fix versions |
roles.json |
Role-to-member mappings |
issues.json |
All issues — every field, changelog history |
worklogs/worklogs.json |
Time tracking entries per issue |
attachments/<KEY>/ |
Binary attachment files, streamed to disk |
boards.json |
Agile board list |
board_<id>_config.json |
Board columns and swimlanes |
board_<id>_sprints.json |
Sprint history |
manifest.json |
File index — presence marks the backup as complete |
Restore Phases
Each phase can be toggled individually and is fully resumable via restore_progress.json:
| Phase | What happens | Endpoint |
|---|---|---|
| 1 | Create issues — epics first, then regular, then subtasks | POST /rest/api/3/issue |
| 2 | Restore issue links (outward only, no duplicates) | POST /rest/api/3/issueLink |
| 3 | Add comments — original author and date prepended as text | POST /rest/api/3/issue/{key}/comment |
| 4 | Add worklogs — original author prepended as text | POST /rest/api/3/issue/{key}/worklog |
| 5 | Upload attachments — skips duplicates by filename | POST /rest/api/3/issue/{key}/attachments |
Issue key mapping between source and target is saved in key_mapping.json inside the backup directory.
Known Limitations
These are Jira Cloud REST API constraints — not tool limitations:
| Data | Status | Notes |
|---|---|---|
| Timestamps (created/updated) | Not restorable | Cloud API blocks setting these fields |
| Changelog / history | Backup only | No write endpoint exists |
| Comment / worklog author | Text attribution | [Originally by Name on Date] prepended |
| Reporter / Assignee | Conditional | Restored only if the user's email exists in the target instance |
| Issue status | Resets to default | Workflow transitions not yet automated |
Issue keys (e.g. KEY-123) |
Reassigned | Cloud assigns new keys; old→new mapping is saved |
Project Structure
jira-project-backup-restore/
├── main.py # Entry point — interactive menu + CLI flags
├── .env.example # Configuration template
├── requirements.txt # Python dependencies
│
├── jira_tool/
│ ├── config.py # .env loader and validation
│ ├── auth.py # Session builder (API token / cookie auth)
│ ├── api_client.py # HTTP client with retry and rate-limit handling
│ ├── backup.py # BackupManager — orchestrates full project backup
│ ├── restore.py # RestoreManager — 5-phase restore
│ ├── export.py # CSV export and backup statistics
│ ├── attachments.py # Standalone attachment uploader
│ ├── adf.py # Atlassian Document Format helpers
│ ├── progress.py # Resumability tracker
│ ├── utils.py # Logging, JSON I/O, utilities
│ ├── cli.py # Console-script entry point
│ └── menu.py # Interactive CLI menu
│
└── backups/ # Backup output directory (gitignored)
└── PROJ_20260322_143000/
├── manifest.json # Completion marker + file index
├── issues.json
├── attachments/
└── ...
Configuration Reference
All settings live in .env (copy from .env.example):
| Variable | Required | Default | Description |
|---|---|---|---|
JIRA_URL |
Yes | — | Jira Cloud base URL (no trailing slash) |
JIRA_EMAIL |
Yes* | — | Account email for API token auth |
JIRA_API_TOKEN |
Yes* | — | API token — generate here |
JIRA_COOKIE_HEADER |
Alt* | — | Full Cookie: header value for SSO auth |
JIRA_VERIFY_SSL |
No | true |
Set false to skip SSL verification |
BACKUP_ROOT |
No | ./backups |
Directory where backups are written |
PAGE_SIZE |
No | 100 |
Issues per API page (max 100) |
MAX_RETRIES |
No | 3 |
Retry count on transient failures |
READ_TIMEOUT |
No | 30 |
HTTP read timeout in seconds |
API_DELAY |
No | 0.2 |
Seconds to wait between API calls |
INCLUDE_ATTACHMENTS |
No | true |
Download attachment binary files |
INCLUDE_CHANGELOG |
No | true |
Include field change history in issues |
INCLUDE_WORKLOGS |
No | true |
Include time tracking entries |
LEGACY_KEY_JQL_TEMPLATE |
No | — | JQL template for standalone attachment upload |
* Either
JIRA_EMAIL+JIRA_API_TOKENorJIRA_COOKIE_HEADERis required.
Requirements
- Python 3.10+
requests>= 2.28python-dotenv>= 1.0
Changelog
See CHANGELOG.md for the full version history.
Contributing
See CONTRIBUTING.md for the versioning policy and how to bump the version when making changes.
License
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jira_project_backup_restore-1.3.2.tar.gz.
File metadata
- Download URL: jira_project_backup_restore-1.3.2.tar.gz
- Upload date:
- Size: 33.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
520a7ac67026c405df04838abfa95059daf68018749a9a4e9c94bd40da640a7d
|
|
| MD5 |
3a85d956f0df78f1a780a1cc63903a3f
|
|
| BLAKE2b-256 |
54b0cfaa360e937e15b44c9a6157fb22c7bfd7c8dc2016d7402078de01150566
|
Provenance
The following attestation bundles were made for jira_project_backup_restore-1.3.2.tar.gz:
Publisher:
publish.yml on davidmalko87/jira-project-backup-restore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jira_project_backup_restore-1.3.2.tar.gz -
Subject digest:
520a7ac67026c405df04838abfa95059daf68018749a9a4e9c94bd40da640a7d - Sigstore transparency entry: 1453681868
- Sigstore integration time:
-
Permalink:
davidmalko87/jira-project-backup-restore@c9599dfe92cd8edd73bc740f8d86c80f18c8ac76 -
Branch / Tag:
refs/tags/v1.3.2 - Owner: https://github.com/davidmalko87
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c9599dfe92cd8edd73bc740f8d86c80f18c8ac76 -
Trigger Event:
push
-
Statement type:
File details
Details for the file jira_project_backup_restore-1.3.2-py3-none-any.whl.
File metadata
- Download URL: jira_project_backup_restore-1.3.2-py3-none-any.whl
- Upload date:
- Size: 38.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
25f09986f66a57a484fe8d29a68030ef2474d5b6d47bd6c0c72d7ad8f9de6772
|
|
| MD5 |
0ce12260b952d5f586c94f075845aeb9
|
|
| BLAKE2b-256 |
999c7b0586340e9158fc729a77d42ec581966a43edc1c0c48c2df6eb410c004c
|
Provenance
The following attestation bundles were made for jira_project_backup_restore-1.3.2-py3-none-any.whl:
Publisher:
publish.yml on davidmalko87/jira-project-backup-restore
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jira_project_backup_restore-1.3.2-py3-none-any.whl -
Subject digest:
25f09986f66a57a484fe8d29a68030ef2474d5b6d47bd6c0c72d7ad8f9de6772 - Sigstore transparency entry: 1453682103
- Sigstore integration time:
-
Permalink:
davidmalko87/jira-project-backup-restore@c9599dfe92cd8edd73bc740f8d86c80f18c8ac76 -
Branch / Tag:
refs/tags/v1.3.2 - Owner: https://github.com/davidmalko87
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c9599dfe92cd8edd73bc740f8d86c80f18c8ac76 -
Trigger Event:
push
-
Statement type: