Duplicate & Delete a Report
Clone a report and its data sources, or hard-delete a report and its data sources, with the duplicateReport and deleteReport mutations.
Use the duplicateReport mutation to clone a report, and the deleteReport mutation to remove one. Duplicating copies the report’s title, description, config, and every data source — but not its shared collaborators; the duplicate starts private to you, and you become its creator. Deleting hard-deletes the report and cascade-deletes its data sources, and is restricted to the report’s creator.
A report aggregates records (Todo objects) across one or more workspaces (Project objects); see the Reports overview for the full model.
Request
Duplicate a report. The input argument is optional — omit it to accept the default title.
mutation DuplicateReport {
duplicateReport(id: "report_123") {
id
title
createdAt
}
}Pass a title to name the copy explicitly.
mutation DuplicateReportWithTitle {
duplicateReport(id: "report_123", input: { title: "Q4 Pipeline (working copy)" }) {
id
title
}
}Delete a report. deleteReport returns Boolean!, so it takes no sub-selection.
mutation DeleteReport {
deleteReport(id: "report_123")
}Parameters
duplicateReport
| Parameter | Type | Required | Description |
|---|---|---|---|
id | String! | Yes | ID of the report to duplicate. You must have view access (creator, EDITOR, or VIEWER). |
input | DuplicateReportInput | No | Options for the copy. Omit entirely to use defaults. |
DuplicateReportInput
| Parameter | Type | Required | Description |
|---|---|---|---|
title | String | No | Title for the copy. If omitted, the copy is titled "Copy of <original title>". |
deleteReport
| Parameter | Type | Required | Description |
|---|---|---|---|
id | String! | Yes | ID of the report to delete. You must be the report’s creator (see below). |
Response
duplicateReport returns the newly created Report.
{
"data": {
"duplicateReport": {
"id": "clm4n8qwx000008l0g4oxdqn7",
"title": "Copy of Q4 Pipeline",
"createdAt": "2026-05-29T14:03:11.000Z"
}
}
}deleteReport returns true on success.
{
"data": {
"deleteReport": true
}
}Returns — duplicateReport
The mutation returns the new Report. The duplicate lives in the same organization as the original, and you are its creator.
| Field | Type | Description |
|---|---|---|
id | ID! | Unique identifier of the new report. |
uid | String! | Stable UID for the report. |
title | String! | Title of the copy. |
description | String | Description copied from the original. |
config | JSONObject | Opaque view configuration copied from the original (see note). |
createdBy | User! | The user who ran the duplication. The caller always becomes the creator. |
dataSources | [ReportDataSource!]! | Data sources copied from the original, each recreated with a fresh uid. |
reportUsers | [ReportUser!]! | Empty — collaborators are not copied. The duplicate starts private to you. |
lastGeneratedAt | DateTime | null on a fresh duplicate until aggregations are first computed. |
createdAt | DateTime! | When the copy was created. |
updatedAt | DateTime! | When the copy was last modified. |
For the full Report and ReportDataSource field reference (including the computed projectIds union and the todos / todoCount / aggregations query surface), see Query Reports and Report Data & Aggregations.
Returns — deleteReport
| Type | Description |
|---|---|
Boolean! | true when the report and its data sources are deleted. Never false. |
What gets copied
duplicateReport deep-copies the report into a new record in the same organization:
- The report — a new
Reportwith a freshidanduid. Thetitle(defaulting to"Copy of <title>"),description, andconfigare copied verbatim. - All data sources — every
ReportDataSourceis recreated with a freshuid, preserving itsname,sourceType,projectIds,filters, andorder. A data source withprojectIds: null(all workspaces the creator can access) staysnullon the copy. - Creator — the calling user becomes
createdBy, regardless of who created the original.
It deliberately does not copy:
- Shared collaborators —
reportUsersis not carried over. The duplicate starts private to you; re-share it withupdateReportif needed.
Because each data source resolves projectIds: null against the report creator’s workspace access, a copied data source on the duplicate resolves against your access, not the original creator’s. If you have access to fewer workspaces than the original creator, the duplicate’s record set can differ from the original’s.
deleteReport hard-deletes the report — there is no soft-delete, archive, or undo. Its data sources are cascade-deleted with it. The underlying records (Todo objects) and workspaces are untouched; only the report and its configuration are removed.
Errors
| Code | When |
|---|---|
UNAUTHENTICATED | No valid credentials on the request. |
REPORT_NOT_FOUND | No report matches id for the caller. For duplicateReport this also covers no view access; for deleteReport it also covers any caller who is not the creator (an EDITOR or VIEWER simply finds no matching report). |
{
"errors": [
{
"message": "Report was not found.",
"extensions": { "code": "REPORT_NOT_FOUND" }
}
]
}Omitting the required id is rejected by GraphQL as a non-null validation error before the resolver runs — it is not a Blue error code.
Permissions
The two mutations sit at opposite ends of the report permission model.
| Mutation | Required access |
|---|---|
duplicateReport | View access — creator, or a shared reportUser with role EDITOR or VIEWER. |
deleteReport | Creator only. Shared EDITOR and VIEWER collaborators cannot delete. |
Anyone who can see a report can duplicate it (the duplicate is theirs, sharing nothing back to the original). Deleting is the most restricted report operation — even an EDITOR who can update the report cannot delete it. A caller who lacks the required access receives REPORT_NOT_FOUND rather than a distinct permission error.
The config field is a JSONObject — an opaque key/value blob whose internal shape is defined by the app, not the GraphQL schema. duplicateReport copies it as-is.
Related
- Reports overview — the report model, data sources, and how reports relate to records.
- Create a Report — build a report from scratch.
- Query Reports — fetch a report by id or list reports, with the full
Reportfield reference. - Manage Report Access — update a report and share it with
EDITOR/VIEWERcollaborators. - Report Data & Aggregations — read the records, counts, and aggregations a report produces.