Laver docs
Open Laver
Boards and tickets

Importing from Trello, Jira, ClickUp, Microsoft Planner and a spreadsheet#

You can create a board from an export file taken out of Trello, Jira, ClickUp or Microsoft Planner. You can also import your own Spreadsheet — any CSV or Excel workbook (.xlsx) at all — into a board you already have, by saying which of its columns holds which field. Nothing is connected to those products — you export a file, and Laver reads it. The file never leaves your browser except as the body of the request that creates the board.

Where it is#

In the sidebar, click the three dots beside the Boards heading and choose New board. Underneath the name field and the template picker there is a line reading or import from Trello, Jira, ClickUp or Microsoft Planner (JSON or CSV). Click it and choose your file.

You do not tell Laver which product the file came from. It works that out from the file itself, so choosing the wrong option is not a mistake you can make. If the file is not one it recognises, you get a message saying so and nothing is created.

Getting the file out of each product#

Trello#

Board → Show menu → More → Print, export and share → Export as JSON.

One file for the whole board. Lists become status columns in their existing order; cards become tickets. Archived cards and cards on archived lists are skipped, and card labels become workspace labels, keeping roughly their Trello colour.

Jira#

Either of these works:

  • CSV — from the issue search, Export → CSV (all fields). This is the button most people find, and it is the easier one.
  • JSON — the response body of GET /rest/api/3/search, saved to a file. Use this if you are already scripting against the Jira API.

Statuses become columns in the order they are first seen — a search result carries no column ordering, so there is nothing better to go on. Ticket titles keep their issue key, so PROJ-14 Rotate the signing key stays the thing everybody has been calling it.

ClickUp#

Either of these works:

  • CSVList → ⋯ → Download CSV.
  • JSON — the response body of GET /api/v2/list/{list_id}/task.

Tags become labels. With the JSON export, columns are ordered by ClickUp's own orderindex; the CSV does not carry it, so columns come out in first-seen order instead.

Microsoft Planner#

CSVPlan → ⋯ → Export plan to Excel, then save the workbook as CSV.

Planner's buckets become your status columns, in the order they first appear. A task's Labels become workspace labels, and its Progress value comes across as a label too, so "In progress" and "Completed" survive as something you can filter on rather than being lost.

Importing a whole account, not one board#

A Jira export does not have to be one project. Search across everything — project in (PROJ, OPS, SUP), or no project clause at all — and export that, and the file holds your account. A ClickUp export taken at the space rather than at a list is the same thing.

Laver reads the file, sees that it covers more than one, and asks:

This Jira export covers 3 projects, not one board:

  • Platform (PROJ) — 84 tickets
  • Operations (OPS) — 31 tickets
  • Support (SUP) — 12 tickets

Importing it makes 3 boards, one per project. A project you have imported before is refreshed rather than imported a second time.

Say yes and you get one board per project, imported one after another, each named after its own project and each with only its own status columns. You end up where you would have got to by exporting three times out of Jira, from one file and one click.

Worth knowing:

  • Each board is its own import. Re-uploading the same account-wide file later updates all of them, the same way re-importing a single board does. Each board is matched on its own project key or list id.
  • The 2,000 ticket limit is per project, for the JSON exports. An account of six projects with 500 issues each imports fine. A CSV is read up to the limit before it is divided, so a CSV over 2,000 rows is still refused — export those projects separately, or use the JSON.
  • A row belonging to no project keeps the file whole. If some rows carry no project at all, splitting would leave them behind, so the whole file goes onto one board instead — what has always happened.
  • If one board fails, the ones already imported are kept, and the message names the project it stopped at. Nothing is rolled back behind your back.

Trello and Planner exports are one board each by definition, so this never comes up for them.

Your own spreadsheet#

The four above are recognised from the file. A spreadsheet you have been keeping yourself cannot be: Ticket, Notes, Stage and Owner are headings somebody chose, and no amount of sniffing will work them out. So this one asks instead.

Open the board you want the tickets to land on, then ⋯ → Import tickets (.csv, .xlsx). Choose the file and Laver reads its header row; you then pick, per field, which column holds it:

Title (the only one required), description, status, group, priority, start date, due date, labels, assignees, an ID column, and any custom field this board has.

Labels and assignees can be several values in one cell — say what separates them, a comma by default. Assignees are matched on email, against people who are already members of the workspace. Nobody is invited by an import.

Excel workbooks#

A .xlsx saved by Excel, LibreOffice, Google Sheets or Numbers can be chosen directly — there is no need to save it as CSV first. It is read into the same rows a CSV becomes, so everything above and below applies to it unchanged.

Worth knowing about a workbook specifically:

  • The first sheet is the one that imports. A ticket import is one table; other sheets in the file are ignored.
  • Date cells import as dates. A workbook stores 2026-09-14 as the number 46279 and says elsewhere that it is a date, so a due-date column arrives as a date rather than a five-digit number.
  • Formulas import as their last calculated value, which is what the file carries. A formula the spreadsheet never calculated arrives empty.
  • Formatting is not imported. 1234.5 comes across as 1234.5, not £1,234.50, and bold or coloured text arrives as plain text.
  • .xls is not read. The old binary format is a different thing entirely — open it and save as .xlsx or .csv.

Statuses this board has no column for#

Importing into a board you already set up will not add columns to it. If the file says Icebox and your board has no Icebox, the preview says so and offers three answers for each value:

  • Put in column — treat that value as one of your existing columns.
  • Skip these rows — leave them out entirely.
  • Or set anything still unresolved to a single fallback column.

With no answer given, those rows do not import and are listed with the reason.

Importing with no board selected — through the API, without board_uuid — behaves like the vendor importers instead: a new board is created with one column per value in the file, so nothing can be unresolved.

The preview#

Before anything is written you get four counts — to import, already imported, unresolved, invalid — and a list of the rows behind them with a reason each. These are not estimates: the server runs the import for real and rolls it back, so the numbers are the ones that happened.

Re-importing a spreadsheet#

Rows already imported are skipped, not updated. A row's identity is a hash of its own content unless you mapped an ID column, so a row that matches is one that has not changed — and writing it back would undo whatever you have done to that ticket since. Map an ID column if you want later edits to the spreadsheet to update the tickets it made.

What comes across#

Comes across Does not
The board and its name Attachments
Status columns Comments and history
Ticket titles Assignees
Ticket descriptions Due dates, priorities, estimates
Labels, tags and colours Subtasks and links between tickets

Descriptions arrive as plain text. Jira Cloud stores them in Atlassian Document Format rather than as a string, so the text is flattened out of it — you will see the words, not the formatting.

Importing the same file twice#

Re-importing is safe and is the intended way to bring a board up to date. The second import finds the board the first one made and updates it, rather than making a second board:

  • Tickets that already exist are updated in place.
  • Tickets that are new in the export are added.
  • Tickets you have since deleted in Laver are not brought back.

Matching is by the vendor's own identifier — the Trello board id, the Jira project key, the ClickUp list id. One exception: a ClickUp CSV carries the list's name rather than its id, so if you rename a list in ClickUp and export it again, that import creates a new board. A name is not an identifier, and silently overwriting the wrong board would be worse.

Limits#

  • 2,000 tickets per import. A bigger export is refused with a message saying how many it contained.
  • The workspace's own plan limits still apply — an import that would take you past your board limit is refused like any other board.

If it does not work#

The messages are specific, and each one names the thing that is missing:

  • "That does not look like a Trello board export" — the JSON has no lists and cards arrays. You have probably exported a single card, or a whole workspace rather than one board.
  • "That does not look like a Jira CSV export — no 'Issue key' column" — the CSV came from somewhere else, or from a Jira export with the key column deselected.
  • "That does not look like a ClickUp CSV export — no 'Task Name' column" — same, for ClickUp.
  • "That file is not JSON or CSV" — the file is something else, or was saved with the wrong extension.
  • "That file could not be read as an Excel workbook (.xlsx)" — the file is named .xlsx but is not a workbook. Usually a CSV that was renamed rather than saved as one.
  • "That does not look like an Excel workbook — it has no xl/workbook.xml" — a zip of something else, or an .xls or Numbers file. Save it as .xlsx or .csv first.

Doing it over the API#

The same thing, if you are scripting it:

text
POST /workspaces/{workspace_uuid}/imports
{
  "source": "trello" | "jira" | "clickup" | "jira-csv" | "clickup-csv"
          | "microsoft-tasks" | "spreadsheet",
  "export": <the parsed JSON object, or the CSV file's text>,
  "name":   "Optional board name",
  "project": "PROJ"
}

project is optional and only means anything for jira, jira-csv, clickup and clickup-csv. It imports the rows of that one project (Jira) or list (ClickUp) and leaves the rest of the file out, which is how an account-wide export becomes one board each: call this once per project. To find out what a file covers first:

text
POST /workspaces/{workspace_uuid}/imports/projects
{ "source": "jira", "export": <the export> }

→ { "label": "project",
    "projects": [ { "key": "PROJ", "name": "Platform", "tickets": 84 }, … ] }

label is project for Jira and list for ClickUp, and is null with an empty list for the three sources one file of which is always one board. A project reported with an empty key is rows that carry no project; import the file without project rather than splitting it, or those rows are left behind. Asking for a project the file does not contain is a 400, not an empty board.

For spreadsheet, three more fields:

text
{
  "source":     "spreadsheet",
  "export":     "<the CSV file's text>",
  "board_uuid": "<the board to import into; omit to create one>",
  "separator":  ",",
  "mapping": {
    "title": "Ticket", "description": "Notes", "status": "Stage",
    "assignees": "Owner", "labels": "Tags", "due_date": "Due",
    "custom_fields": { "<field uuid>": "Estimate" }
  },
  "statuses": {
    "map":      { "Icebox": "Backlog" },
    "skip":     ["Archived"],
    "fallback": "Backlog"
  }
}

To send a workbook instead of CSV text, base64-encode the .xlsx file and add "format": "xlsx" — a workbook is a zip, so it cannot travel as JSON text. All four import endpoints take the field. The workbook is unzipped to rows before any parser runs, so everything after the file is read is identical either way.

text
{
  "source": "spreadsheet",
  "format": "xlsx",
  "export": "<the .xlsx file, base64-encoded>",
  ...
}

POST /workspaces/{workspace_uuid}/imports/columns with just { "export": "<the CSV text>" } — or the workbook and "format": "xlsx" — returns the file's column headings and a few sample rows, read with the same parser the import uses. .../imports/preview takes the identical body as the import and reports what it would do without doing it.

201 with the new board on a first import, 200 with "reimported": true when it updated one that already existed. See the API reference.