Duplicate dashboard by ID
curl --request POST \
--url https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Jakarta Hub - Daily (copy)"
}
'import requests
url = "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate"
payload = { "name": "Jakarta Hub - Daily (copy)" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Jakarta Hub - Daily (copy)'})
};
fetch('https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Jakarta Hub - Daily (copy)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate"
payload := strings.NewReader("{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"code": 201,
"message": "Dashboard has been added successfully.",
"data": {
"_id": "66f9a1c2e4b0a7d3c1f20a12",
"organizationId": "6650c2a1f3b9e4001c7d2a10",
"schemaVersion": 1,
"name": "Jakarta Hub - Daily (copy)",
"description": "Morning stand-up view",
"sharedRoleIds": [],
"hubScope": {
"mode": "selected",
"hubIds": [
"6650c2a1f3b9e4001c7d2c30"
]
},
"timeRange": {
"preset": "last_7d"
},
"grid": {
"columns": 12
},
"widgets": [
{
"cardId": "crd_01J8ZR1A2B3C4D5E6F7G8H9J0K",
"widgetId": "66fa0c11e4b0a7d3c1f20c01",
"widgetName": "Total Tasks",
"layout": {
"w": 3,
"h": null
},
"widget": {
"schemaVersion": 1,
"name": "Total Tasks",
"description": "Tasks whose start time falls in the selected range, across every status.",
"category": "overview",
"viz": "kpi",
"spec": {
"specVersion": 1,
"dataSourceId": "task",
"timeField": "startTime",
"measures": [
{
"id": "m1",
"fn": "count"
}
],
"dimensions": [],
"filters": []
},
"composite": null,
"content": null,
"defaultLayout": {
"w": 3,
"h": null
}
}
},
{
"cardId": "crd_01J8ZR1A2B3C4D5E6F7G8H9J0M",
"widgetId": "66fa0c11e4b0a7d3c1f20c02",
"widgetName": "Tasks by Status",
"layout": {
"w": 6,
"h": 6,
"x": 3,
"y": 0
},
"widget": {
"schemaVersion": 1,
"name": "Tasks by Status",
"description": "Task count per status in the selected range.",
"category": "taskStatus",
"viz": "donut",
"spec": {
"specVersion": 1,
"dataSourceId": "task",
"timeField": "startTime",
"measures": [
{
"id": "m1",
"fn": "count"
}
],
"dimensions": [
{
"id": "d1",
"kind": "terms",
"field": "status",
"limit": 3
}
],
"filters": []
},
"composite": null,
"content": null,
"defaultLayout": {
"w": 6,
"h": 6
}
}
}
],
"origin": {
"kind": "duplicate",
"sourceId": "66f9a1c2e4b0a7d3c1f20a11",
"sourceSchemaVersion": 1,
"copiedAt": "2026-09-30T09:40:18+07:00"
},
"createdBy": "[email protected]",
"updatedBy": "[email protected]",
"createdTime": "2026-09-30T02:40:18.004000Z",
"updatedTime": "2026-09-30T02:40:18.004000Z"
}
}{
"status": false,
"message": "This template references widget definition(s) that cannot be resolved: Tasks by Status.",
"failedCode": "dydsh-037"
}{
"status": false,
"message": "Unauthenticated.",
"failedCode": "auth-034"
}{
"status": false,
"message": "Access denied. You do not have permission for add dashboard. Please contact your admin to request access.",
"failedCode": "sys-035"
}{
"status": false,
"code": 404,
"message": "Data not found. Please check the ID or reference number and try again.",
"data": [],
"failedCode": "dydsh-033"
}{
"status": false,
"code": 422,
"message": "This dashboard was saved by a newer version of MileApp and cannot be opened here. Please refresh the page and try again.",
"data": [],
"failedCode": "dydsh-040"
}{
"status": false,
"code": 500,
"message": "something_wrong",
"failedCode": "dydsh-045"
}Dashboard
Duplicate dashboard by ID
Creates a copy of any dashboard the caller can see. The copy is owned by the caller, starts unshared, and every card gets its own widget row. When name is omitted, the copy is named Copy of {source name}.
POST
/
dynamic-dashboard
/
{id}
/
duplicate
Duplicate dashboard by ID
curl --request POST \
--url https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Jakarta Hub - Daily (copy)"
}
'import requests
url = "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate"
payload = { "name": "Jakarta Hub - Daily (copy)" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Jakarta Hub - Daily (copy)'})
};
fetch('https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'Jakarta Hub - Daily (copy)'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate"
payload := strings.NewReader("{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://apiweb.mile.app/api/v3/dynamic-dashboard/{id}/duplicate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"Jakarta Hub - Daily (copy)\"\n}"
response = http.request(request)
puts response.read_body{
"status": true,
"code": 201,
"message": "Dashboard has been added successfully.",
"data": {
"_id": "66f9a1c2e4b0a7d3c1f20a12",
"organizationId": "6650c2a1f3b9e4001c7d2a10",
"schemaVersion": 1,
"name": "Jakarta Hub - Daily (copy)",
"description": "Morning stand-up view",
"sharedRoleIds": [],
"hubScope": {
"mode": "selected",
"hubIds": [
"6650c2a1f3b9e4001c7d2c30"
]
},
"timeRange": {
"preset": "last_7d"
},
"grid": {
"columns": 12
},
"widgets": [
{
"cardId": "crd_01J8ZR1A2B3C4D5E6F7G8H9J0K",
"widgetId": "66fa0c11e4b0a7d3c1f20c01",
"widgetName": "Total Tasks",
"layout": {
"w": 3,
"h": null
},
"widget": {
"schemaVersion": 1,
"name": "Total Tasks",
"description": "Tasks whose start time falls in the selected range, across every status.",
"category": "overview",
"viz": "kpi",
"spec": {
"specVersion": 1,
"dataSourceId": "task",
"timeField": "startTime",
"measures": [
{
"id": "m1",
"fn": "count"
}
],
"dimensions": [],
"filters": []
},
"composite": null,
"content": null,
"defaultLayout": {
"w": 3,
"h": null
}
}
},
{
"cardId": "crd_01J8ZR1A2B3C4D5E6F7G8H9J0M",
"widgetId": "66fa0c11e4b0a7d3c1f20c02",
"widgetName": "Tasks by Status",
"layout": {
"w": 6,
"h": 6,
"x": 3,
"y": 0
},
"widget": {
"schemaVersion": 1,
"name": "Tasks by Status",
"description": "Task count per status in the selected range.",
"category": "taskStatus",
"viz": "donut",
"spec": {
"specVersion": 1,
"dataSourceId": "task",
"timeField": "startTime",
"measures": [
{
"id": "m1",
"fn": "count"
}
],
"dimensions": [
{
"id": "d1",
"kind": "terms",
"field": "status",
"limit": 3
}
],
"filters": []
},
"composite": null,
"content": null,
"defaultLayout": {
"w": 6,
"h": 6
}
}
}
],
"origin": {
"kind": "duplicate",
"sourceId": "66f9a1c2e4b0a7d3c1f20a11",
"sourceSchemaVersion": 1,
"copiedAt": "2026-09-30T09:40:18+07:00"
},
"createdBy": "[email protected]",
"updatedBy": "[email protected]",
"createdTime": "2026-09-30T02:40:18.004000Z",
"updatedTime": "2026-09-30T02:40:18.004000Z"
}
}{
"status": false,
"message": "This template references widget definition(s) that cannot be resolved: Tasks by Status.",
"failedCode": "dydsh-037"
}{
"status": false,
"message": "Unauthenticated.",
"failedCode": "auth-034"
}{
"status": false,
"message": "Access denied. You do not have permission for add dashboard. Please contact your admin to request access.",
"failedCode": "sys-035"
}{
"status": false,
"code": 404,
"message": "Data not found. Please check the ID or reference number and try again.",
"data": [],
"failedCode": "dydsh-033"
}{
"status": false,
"code": 422,
"message": "This dashboard was saved by a newer version of MileApp and cannot be opened here. Please refresh the page and try again.",
"data": [],
"failedCode": "dydsh-040"
}{
"status": false,
"code": 500,
"message": "something_wrong",
"failedCode": "dydsh-045"
}Authorizations
Use a valid Bearer token to authenticate.
Path Parameters
Source dashboard _id
Body
application/json
Optional name
Name of the copy; defaults to Copy of {source name}
Maximum string length:
200