# Migrate Jira to Monday.com

> Monday organises work as boards inside folders, so one Jira project fans out into several boards.

Source: https://migratly.dev/migrate/jira-to-monday/

Migratly migrates Jira to Monday.com by reading both APIs live, deriving the mapping between them, and
presenting it for approval before anything is written. This pair covers **13 entity types**
and **70 field mappings**: 35 carry across intact, 30 are flagged as lossy,
partial, dropped or needing another route, and 5 need a decision from you. The Jira side is
read-only for the whole run.

## How the structure changes

- Each Jira project becomes a Monday folder.
- Inside that folder, separate boards are created for Tasks, Epics and a Bugs Queue. Board columns come from the mapped Jira fields.
- Jira sprints become groups inside the project's Tasks board.
- Issues and epics are written as items only after their board exists — creating the board and filling it are two separate waves.
- Issue links become Monday dependencies in the last wave.

## Entity map

| Jira | Monday.com | Wave | Fields |
|---|---|---|---|
| Project | Folder | 0 | 2 |
| User | User | 0 | 4 |
| Epic | Epics | 1 | 3 |
| Issue | Tasks | 1 | 5 |
| Sprint | Group | 1 | 4 |
| Sprint | Sprints | 1 | 1 |
| Epic | Item | 2 | 4 |
| Issue | Item | 2 | 31 |
| Sprint | Item | 2 | 4 |
| Attachment | File | 3 | 2 |
| Comment | Update | 3 | 3 |
| Sub-task | Subitem | 3 | 4 |
| IssueLink | Dependency | 4 | 3 |

## Field coverage

### Project → Folder

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `name` | `name` | Full |  |
| `key` | no equivalent | Internal | Used as the collection_key template prefix for boards inside this folder (e.g. KAN_tasks, KAN_epics). |

### User → User

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `accountId` | no equivalent | Lossy | Monday users have numeric IDs unrelated to Jira accountId — joined by email. |
| `displayName` | `name` | Full |  |
| `emailAddress` | `email` | Full | Primary join key — Jira users must already exist in the target Monday workspace with the same email. |
| `active` | no equivalent | Dropped | Monday does not expose user active status via API; admin-only setting. |

### Epic → Epics

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `summary` | `item_name` | Internal |  |
| `status.name` | `column.status` | Partial |  |
| `customfield_10015` | `column.date` | Full | Jira Cloud epic start date custom field. |

### Issue → Tasks

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `summary` | `item_name` | Internal | Driver for declaring the board has a primary 'Name' column — item_name is the native title field on every Monday board. |
| `status.name` | `column.status` | Partial | Status column must be created on the board with Jira's status labels. Unmapped statuses fall back to the board default. |
| `priority.name` | `column.priority` | Full |  |
| `duedate` | `column.date` | Full |  |
| `labels` | `column.dropdown` | Full |  |

### Sprint → Group

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `name` | `title` | Full |  |
| `state` | no equivalent | Dropped | Monday Groups have no state/status concept — sprint state inferred from issue completion. |
| `startDate` | no equivalent | Dropped | Monday Groups have no start/end date fields. |
| `goal` | no equivalent | Workaround | Sprint goal stored as the first Update on the first item of the group (workaround). |

### Sprint → Sprints

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `name` | `item_name` | Internal | Driver for declaring the Sprints board's primary Name column. |

### Epic → Item

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `summary` | `item_name` | Full |  |
| `description` | `column_values.long_text` | Partial | ADF → plain/markdown. |
| `status.name` | `column_values.status` | Partial |  |
| `customfield_10015` | `column_values.date` | Full | Epic start date. |

### Issue → Item

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `summary` | `item_name` | Full |  |
| `description` | `column_values.long_text` | Partial | ADF rich text flattens to plain text/markdown. For rich content, also append as an Update. |
| `status.name` | `column_values.task_status` | Partial | Maps to source-template's `task_status` (Status) column on cloned Tasks board. |
| `priority.name` | `column_values.priority` | Full |  |
| `assignee.accountId` | `column_values.task_owner` | Full |  |
| `reporter.accountId` | no equivalent | Workaround | Monday items don't have a reporter field — reporter prepended in description or as an Update. |
| `labels` | `column_values.labels` | Full |  |
| `duedate` | `column_values.date` | Full |  |
| `created` | no equivalent | Dropped | Monday's created_at is set by the API at item creation time — cannot override. |
| `key` | `column_values.issue_key` | Full |  |
| `customfield_10016` | `column_values.numbers` | Partial | Story points custom field ID varies per Jira instance — should be discovered at runtime. |
| `customfield_10020` | `group_id` | Full | Sprint custom field — items placed in the matching Sprint Group on the cloned Tasks board. customfield_10020 is a LIST of sprint dicts; pipe picks the most-current (active>future>closed) and extracts .name. _resolve_group looks up group_map[:] which the Sprint→Group entity populated. |
| `customfield_10020` | `column_values.task_sprint` | Full | Cross-board link to the Sprint item on the cloned Sprints board (split from group_id above so _build_properties picks the lookup transform, not the group-name extractor — executor only uses first_route per field_mapping). |
| `parent.key` | `column_values.task_epic` | Full | Cross-board link to the Epic item on the cloned Epics board. Uses the universal id_map lookup — the Epic→Item migration runs first (dependency_level=2) and populates id_map[Record:] with the new item id; this transform resolves that mapping at write time. |
| `issuetype.name` | `column_values.task_type` | Full | Maps to source-template's `task_type` (Type) column on cloned Tasks board. |
| `project.key` | `column_values.project_key` | Internal | Already encoded in board structure (one board per project) — but stored on item too for traceability. |
| `creator.accountId` | `column_values.original_creator` | Workaround | Monday items don't support arbitrary creator override; original creator name stored as text. |
| `fixVersions` | `column_values.fix_versions` | Full |  |
| `versions` | `column_values.affects_versions` | Full |  |
| `components` | `column_values.components` | Full |  |
| `resolution.name` | `column_values.resolution` | Full |  |
| `resolutiondate` | `column_values.date` | Full |  |
| `votes.votes` | no equivalent | Dropped | Vote counts have no decision-grade value post-migration; deliberately dropped. |
| `watches.watchCount` | no equivalent | Dropped | Watch counts deliberately dropped. |
| `workratio` | no equivalent | Dropped | Derived value; not meaningful post-migration. |
| `progress` | no equivalent | Dropped | Time-tracking aggregate; covered elsewhere. |
| `aggregateprogress` | no equivalent | Dropped | Sub-issue roll-up; recomputed in target. |
| `lastViewed` | no equivalent | Dropped | Per-user metadata. |
| `statuscategorychangedate` | no equivalent | Dropped | Derived field; not meaningful post-migration. |
| `statusCategory` | no equivalent | Dropped | Derived from status.name. |
| `id` | no equivalent | Dropped | Internal Jira numeric ID; key preserved instead. |

### Sprint → Item

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `name` | `item_name` | Full |  |
| `goal` | `column_values.sprint_goals` | Full | Maps to cloned Sprints board's `sprint_goals` long_text column. |
| `startDate` | `column_values.sprint_timeline` | Full | Compound timeline value built from startDate + endDate of the same source record via the `object` op (each field reads from source record). Coerce normalises to YYYY-MM-DD. |
| `state` | `column_values.active_sprint` | Full | Map Jira sprint state → checkbox. 'active' → checked, else unchecked. |

### Attachment → File

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `content` | no equivalent | Workaround | Monday API v2 has no native binary upload mutation. Workaround: post the source attachment URL as text in an Update, with auth-protected URLs that may expire. |
| `filename` | no equivalent | Full |  |

### Comment → Update

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `body` | `body` | Partial | ADF → plain text/markdown; Monday Updates support markdown but not arbitrary rich blocks. |
| `author.accountId` | no equivalent | Workaround | Monday Updates can't be posted as another user — author name prepended in body. |
| `created` | no equivalent | Dropped | Monday sets created_at on Updates — cannot override. |

### Sub-task → Subitem

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `summary` | `item_name` | Full |  |
| `parent.key` | `parent_item_id` | Full |  |
| `status.name` | `column_values.status` | Partial |  |
| `assignee.accountId` | `column_values.assignee` | Full |  |

### IssueLink → Dependency

| Jira field | Monday.com field | Coverage | Notes |
|---|---|---|---|
| `inwardIssue.key` | `column_values.dependency` | Full |  |
| `outwardIssue.key` | `column_values.dependency` | Full |  |
| `type.name` | no equivalent | Dropped | Monday dependencies are untyped — blocks/duplicates/relates merge to a single dependency relationship. |

## FAQ

**How does a Jira project map onto Monday.com boards?**

One folder per Jira project, holding a Tasks board, an Epics board and a Bugs Queue board. Splitting by type keeps each board's column schema meaningful, which a single mixed board cannot do.

**Do Jira sprints become anything in Monday.com?**

Sprints become groups inside that project's Tasks board, so the sprint an issue belonged to is still visible after the move.

**Are Jira comments migrated to Monday.com?**

Yes, as updates on the corresponding item. They are written after items exist, and original timestamps are preserved where the Monday API accepts them.

---

Start a migration: https://app.migratly.dev/
