curl --request POST \
--url https://api.dune.com/api/v1/uploads/csv \
--header 'Content-Type: application/json' \
--header 'X-DUNE-API-KEY: <x-dune-api-key>' \
--data '{
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": false
}'
from dune_client.client import DuneClient
dune = DuneClient()
file_path = r'/data/example.csv'
with open(file_path) as file:
data = file.read()
table = dune.upload_csv(
data=str(data),
description="10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
table_name="ten_year_us_interest_rates",
is_private=False
)
import * as fs from "fs/promises";
import { DuneClient, ContentType } from "@duneanalytics/client-sdk";
client = new DuneClient(process.env.DUNE_API_KEY!);
const data = await fs.readFile("./sample_table_insert.csv");
const result = await client.table.uploadCsv({
table_name: "ten_year_us_interest_rates",
description: "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
data,
is_private: false,
});
import requests
url = "https://api.dune.com/api/v1/uploads/csv"
payload = {
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": False
}
headers = {
"X-DUNE-API-KEY": "<x-dune-api-key>",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'X-DUNE-API-KEY': '<x-dune-api-key>', 'Content-Type': 'application/json'},
body: '{"data":"DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23","description":"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10","table_name":"ten_year_us_interest_rates","is_private":false}'
};
fetch('https://api.dune.com/api/v1/uploads/csv', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.dune.com/api/v1/uploads/csv"
payload := strings.NewReader("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
req, _ := http.NewRequest("POST", 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, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dune.com/api/v1/uploads/csv",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}",
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;
}
HttpResponse<String> response = Unirest.post("https://api.dune.com/api/v1/uploads/csv")
.header("X-DUNE-API-KEY", "<x-dune-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
.asString();
{
"full_name": "dune.my_team.dataset_ten_year_us_interest_rates",
"success": true,
"table_name": "ten_year_us_interest_rates"
}{
"error": "Bad Request"
}{
"error": "Invalid API Key"
}{
"error": "Internal error"
}Data Uploads
Upload CSV
Upload a CSV file to create a table with automatic schema inference. The size limit per upload is 500MB. Storage limits: 100MB (free), 1GB (analyst), 15GB (plus).
POST
/
v1
/
uploads
/
csv
curl --request POST \
--url https://api.dune.com/api/v1/uploads/csv \
--header 'Content-Type: application/json' \
--header 'X-DUNE-API-KEY: <x-dune-api-key>' \
--data '{
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": false
}'
from dune_client.client import DuneClient
dune = DuneClient()
file_path = r'/data/example.csv'
with open(file_path) as file:
data = file.read()
table = dune.upload_csv(
data=str(data),
description="10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
table_name="ten_year_us_interest_rates",
is_private=False
)
import * as fs from "fs/promises";
import { DuneClient, ContentType } from "@duneanalytics/client-sdk";
client = new DuneClient(process.env.DUNE_API_KEY!);
const data = await fs.readFile("./sample_table_insert.csv");
const result = await client.table.uploadCsv({
table_name: "ten_year_us_interest_rates",
description: "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
data,
is_private: false,
});
import requests
url = "https://api.dune.com/api/v1/uploads/csv"
payload = {
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": False
}
headers = {
"X-DUNE-API-KEY": "<x-dune-api-key>",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'X-DUNE-API-KEY': '<x-dune-api-key>', 'Content-Type': 'application/json'},
body: '{"data":"DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23","description":"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10","table_name":"ten_year_us_interest_rates","is_private":false}'
};
fetch('https://api.dune.com/api/v1/uploads/csv', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.dune.com/api/v1/uploads/csv"
payload := strings.NewReader("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
req, _ := http.NewRequest("POST", 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, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dune.com/api/v1/uploads/csv",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}",
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;
}
HttpResponse<String> response = Unirest.post("https://api.dune.com/api/v1/uploads/csv")
.header("X-DUNE-API-KEY", "<x-dune-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
.asString();
{
"full_name": "dune.my_team.dataset_ten_year_us_interest_rates",
"success": true,
"table_name": "ten_year_us_interest_rates"
}{
"error": "Bad Request"
}{
"error": "Invalid API Key"
}{
"error": "Internal error"
}Minimum required API key scope:
Read/WriteYou can also upload CSV through the Dune UI by pressing the “create” dropdown.Migrating from the old API? See the Migration Guide for help updating your code.
For working with uploads, keep in mind that:
- File has to be < 500 MB
- Column names in the table can’t start with a special character or digits.
- Consumes credits based on the size of data uploaded.
- Free, Analyst, Plus: 3 credits per GB written, minimum charge is 1 credit
- If you upload to an existing table name, it will delete the old data and overwite it with your new data. Appends are only supported for the
/create,/insertendpoints. - To delete an upload table, you must go to
user settings (dune.com) -> data -> delete.
curl --request POST \
--url https://api.dune.com/api/v1/uploads/csv \
--header 'Content-Type: application/json' \
--header 'X-DUNE-API-KEY: <x-dune-api-key>' \
--data '{
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": false
}'
from dune_client.client import DuneClient
dune = DuneClient()
file_path = r'/data/example.csv'
with open(file_path) as file:
data = file.read()
table = dune.upload_csv(
data=str(data),
description="10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
table_name="ten_year_us_interest_rates",
is_private=False
)
import * as fs from "fs/promises";
import { DuneClient, ContentType } from "@duneanalytics/client-sdk";
client = new DuneClient(process.env.DUNE_API_KEY!);
const data = await fs.readFile("./sample_table_insert.csv");
const result = await client.table.uploadCsv({
table_name: "ten_year_us_interest_rates",
description: "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
data,
is_private: false,
});
import requests
url = "https://api.dune.com/api/v1/uploads/csv"
payload = {
"data": "DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23",
"description": "10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10",
"table_name": "ten_year_us_interest_rates",
"is_private": False
}
headers = {
"X-DUNE-API-KEY": "<x-dune-api-key>",
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(response.text)
const options = {
method: 'POST',
headers: {'X-DUNE-API-KEY': '<x-dune-api-key>', 'Content-Type': 'application/json'},
body: '{"data":"DATE,DGS10,\n2023-12-04,4.28,\n2023-12-05,4.18,\n2023-12-06,4.12,\n2023-12-07,4.14,\n2023-12-08,4.23,\n2023-12-11,4.23","description":"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10","table_name":"ten_year_us_interest_rates","is_private":false}'
};
fetch('https://api.dune.com/api/v1/uploads/csv', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://api.dune.com/api/v1/uploads/csv"
payload := strings.NewReader("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
req, _ := http.NewRequest("POST", 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, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.dune.com/api/v1/uploads/csv",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}",
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;
}
HttpResponse<String> response = Unirest.post("https://api.dune.com/api/v1/uploads/csv")
.header("X-DUNE-API-KEY", "<x-dune-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"data\": \"DATE,DGS10,\\n2023-12-04,4.28,\\n2023-12-05,4.18,\\n2023-12-06,4.12,\\n2023-12-07,4.14,\\n2023-12-08,4.23,\\n2023-12-11,4.23\",\n \"description\": \"10 year daily interest rates, sourced from https://fred.stlouisfed.org/series/DGS10\",\n \"table_name\": \"ten_year_us_interest_rates\",\n \"is_private\": false\n}")
.asString();
Upload via google sheet
To automate the upload of a Google Sheet’s contents to Dune via API, use the following Google Apps Script:function uploadToDune() {
var apiKey = "YOUR_DUNE_API_KEY"; // Replace with your actual Dune API key, keep the quotes
var tableName = "example_table"; // Update with your desired table name
var description = "Example table description";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var range = sheet.getDataRange();
var values = range.getValues();
// Convert data to CSV format
var csvData = "";
for (var i = 0; i < values.length; i++) {
csvData += values[i].join(",") + "\n";
}
var payload = {
data: csvData.trim(),
description: description,
table_name: tableName,
is_private: false
};
var options = {
method: "post",
contentType: "application/json",
headers: {
"X-DUNE-API-KEY": apiKey
},
payload: JSON.stringify(payload)
};
var response = UrlFetchApp.fetch("https://api.dune.com/api/v1/uploads/csv", options);
Logger.log(response.getContentText());
}
- Open your Google Sheet
- Navigate to Extensions → Apps Script
- Replace the script with the code above
- Save and run uploadToDune
- (Optional) For easier execution, you can assign this script to a button in your Google Sheet:
- Click “Insert” in the Google Sheets menu
- Select “Drawing”
- Create a button shape and add text like “Upload to Dune”
- Click “Save and Close”
- Right-click the button and select “Assign script”
- Enter “uploadToDune” as the function name
- Clicking the button will now upload your active sheet’s data to Dune!
Headers
API Key for the service
Query Parameters
Alternative to using the X-Dune-Api-Key header
Body
*/*
payload
Was this page helpful?
⌘I