curl --request PUT \
--url https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule \
--header 'Content-Type: application/json' \
--header 'X-Dune-Api-Key: <x-dune-api-key>' \
--data '
{
"cron_expression": "0 6 * * *",
"performance": "medium",
"expires_at": "<string>"
}
'import requests
url = "https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule"
payload = {
"cron_expression": "0 6 * * *",
"performance": "medium",
"expires_at": "<string>"
}
headers = {
"X-Dune-Api-Key": "<x-dune-api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-Dune-Api-Key': '<x-dune-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({cron_expression: '0 6 * * *', performance: 'medium', expires_at: '<string>'})
};
fetch('https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule', 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://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'cron_expression' => '0 6 * * *',
'performance' => 'medium',
'expires_at' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Dune-Api-Key: <x-dune-api-key>"
],
]);
$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://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule"
payload := strings.NewReader("{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("X-Dune-Api-Key", "<x-dune-api-key>")
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.put("https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule")
.header("X-Dune-Api-Key", "<x-dune-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-Dune-Api-Key"] = '<x-dune-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"created": true,
"cron_expression": "0 6 * * *",
"dashboard_id": 123,
"expires_at": "<string>",
"next_execution_time": "<string>",
"performance": "medium",
"query_id": 1234567,
"type": "query"
}{
"error": "Bad Request"
}{
"error": "Invalid API Key"
}{
"error": "This API request would exceed your configured limits per billing cycle."
}{
"error": "Not allowed to execute query. Query is archived, unsaved or not enough permissions"
}{
"error": "Object not found"
}{
"error": "Conflict - The request conflicts with another request."
}{
"error": "Internal error"
}Set Dashboard Schedule
Refresh the queries of a dashboard on a schedule. Creates the schedule, or replaces all the settings of the one the dashboard has. Every refresh is charged credits at the chosen performance tier. You need to own the dashboard or be an editor or admin of the team that owns it; a team API key can only schedule its own team’s dashboards.
curl --request PUT \
--url https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule \
--header 'Content-Type: application/json' \
--header 'X-Dune-Api-Key: <x-dune-api-key>' \
--data '
{
"cron_expression": "0 6 * * *",
"performance": "medium",
"expires_at": "<string>"
}
'import requests
url = "https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule"
payload = {
"cron_expression": "0 6 * * *",
"performance": "medium",
"expires_at": "<string>"
}
headers = {
"X-Dune-Api-Key": "<x-dune-api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'X-Dune-Api-Key': '<x-dune-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({cron_expression: '0 6 * * *', performance: 'medium', expires_at: '<string>'})
};
fetch('https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule', 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://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'cron_expression' => '0 6 * * *',
'performance' => 'medium',
'expires_at' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Dune-Api-Key: <x-dune-api-key>"
],
]);
$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://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule"
payload := strings.NewReader("{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("X-Dune-Api-Key", "<x-dune-api-key>")
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.put("https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule")
.header("X-Dune-Api-Key", "<x-dune-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.dune.com/api/v1/dashboards/{dashboard_id}/schedule")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["X-Dune-Api-Key"] = '<x-dune-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"cron_expression\": \"0 6 * * *\",\n \"performance\": \"medium\",\n \"expires_at\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"created": true,
"cron_expression": "0 6 * * *",
"dashboard_id": 123,
"expires_at": "<string>",
"next_execution_time": "<string>",
"performance": "medium",
"query_id": 1234567,
"type": "query"
}{
"error": "Bad Request"
}{
"error": "Invalid API Key"
}{
"error": "This API request would exceed your configured limits per billing cycle."
}{
"error": "Not allowed to execute query. Query is archived, unsaved or not enough permissions"
}{
"error": "Object not found"
}{
"error": "Conflict - The request conflicts with another request."
}{
"error": "Internal error"
}Read/WriteUse Cases
- Keep a Dashboard Fresh: Refresh all the queries of a dashboard on a schedule, so viewers see recent data.
- Change a Schedule: Change the frequency or performance tier. The response has
created: falsewhen it replaced a schedule.
Headers
API Key for the service
Path Parameters
Dashboard ID
Body
Schedule settings
CronExpression is a 5-part cron expression in UTC. Supported: every 15, 20 or 30 minutes ("*/15 * * * *"), hourly ("0 * * * *"), every 2, 3, 4, 6, 8 or 12 hours ("0 */6 * * *"), daily ("M H * * *") and weekly ("M H * * D"), where M is 0 or 30.
"0 6 * * *"
Performance is the engine tier each run uses and must be available on your plan. Every run is charged credits at this tier.
small, medium, large "medium"
ExpiresAt stops the schedule after this time. Omitted means no expiration; the free plan caps it at 3 months.
Response
OK
Created is true when the request created the schedule, false when it replaced one.
CronExpression is a 5-part cron expression in UTC.
"0 6 * * *"
DashboardID is set for dashboard schedules.
ExpiresAt is absent when the schedule does not expire.
Performance is the engine tier each run uses.
small, medium, large "medium"
QueryID is set for query and materialized view schedules.
1234567
Type is what the schedule runs. Materialized view refreshes are managed through the /v1/materialized-views endpoints.
query, dashboard, materialized_view "query"
Was this page helpful?