# Dune

> Query blockchain data with Dune: run SQL against decoded data for 100+ chains, run the queries and dashboards your team has already built, and collect the results as rows or CSV. Search the catalogue of tables to find what to query, look up the decoded tables behind any smart contract address, upload your own data to join against onchain activity, and cache expensive queries as materialized views that refresh on a schedule.

App · Cryptocurrency · 30 actions. Web page: https://docs.lodol.com/docs/integrations/dune

## Actions

### Cancel an execution

Stop a run that is still going. Use it to cut a query loose that is taking longer than it is worth: a cancelled run stops consuming compute, though the credits already spent on it stay spent. Only a run still in flight can be cancelled: Dune has nothing to stop once one has finished, and answers that it cannot find the run at all, so check the status first if the run might already be over.

**Inputs**

- Execution (`execution_id`, text, required): The execution to read, as returned by a step that started one (Run a saved query, Run SQL, Start a query run, Start a SQL run, or a materialized view refresh).

**Outputs**

- `cancelled` (true/false): Whether Dune actually stopped it
- `execution_id` (text): The run that was asked to stop

**Example output**

```json
{
  "cancelled": true,
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1"
}
```

### Clear a table

Empty an uploaded table without deleting it: every row goes, the columns stay, and any query or dashboard reading the table keeps working. This is the first half of a full refresh (clear it, then insert the new data), and it frees the storage the old rows were using.

**Inputs**

- Table (`table`, text, required): The uploaded table to act on. Pick one from the list, or type its name as namespace.table_name (the namespace is your Dune username or team handle).

**Outputs**

- `cleared` (true/false): Always true when the step succeeds
- `full_name` (text): The name to write in SQL
- `message` (text): Dune's own message
- `table` (text): namespace.table_name that was cleared

**Example output**

```json
{
  "cleared": true,
  "full_name": "dune.my_team.interest_rates",
  "message": "Table cleared",
  "table": "my_team.interest_rates"
}
```

### Create a table

Create an empty table on Dune with the columns and types you choose, ready for Insert rows to append to. Use this when data arrives repeatedly and has to build up (daily figures, a feed from another system) because rows can be added without replacing what is already there. For a one-off spreadsheet, Upload a CSV is simpler and works out the columns for you. Once the table exists you can join it to any Dune table in SQL.

**Inputs**

- Table name (`table_name`, text, required): What to call the table. Lower case, letters, numbers and underscores; it must not start with a number.
- Columns (`schema`, list, required): The table's columns, as a list of objects. Each needs a 'name' and a 'type' (varchar, double, bigint, boolean, timestamp, date, varbinary, uint256…), and may set 'nullable' to false to require a value.
- Namespace (`namespace`, text): Where the table lives: your Dune username, or your team's handle for a table the team shares. Leave it empty and Dune uses the one the API key belongs to.
- Description (`description`, text): What the table holds and where the data came from. Shown next to the table on Dune.
- Keep it private (`is_private`, true/false): Private tables are visible only to your account or team. Leave off to let anyone on Dune query it. Default: `false`.

**Outputs**

- `already_existed` (true/false): Whether a table of that name was already there
- `column_count` (number): Columns created
- `columns` (list): The columns created
- `example_query` (text): SQL that reads the new table
- `full_name` (text): The name to write in SQL
- `message` (text): Dune's own message
- `name` (text): namespace.table_name: what the table fields take
- `namespace` (text): Where it lives
- `table_name` (text): Its name

**Example output**

```json
{
  "already_existed": false,
  "column_count": 2,
  "columns": [
    {
      "name": "day",
      "type": "timestamp"
    },
    {
      "name": "dgs10",
      "nullable": true,
      "type": "double"
    }
  ],
  "example_query": "select * from dune.my_team.interest_rates limit 10",
  "full_name": "dune.my_team.interest_rates",
  "message": "Table created",
  "name": "my_team.interest_rates",
  "namespace": "my_team",
  "table_name": "interest_rates"
}
```

### Create or update a materialized view

Store a query's results as a table that refreshes on a schedule. Anything reading the view gets an answer instantly and for far fewer credits than re-running the query, which is what makes an expensive query usable in a dashboard or on an hourly workflow. Pick how often it should refresh (Dune allows anything from every 15 minutes to weekly), and Dune keeps it current on its own. Naming a view that already exists updates it; either way a refresh starts straight away.

**Inputs**

- View name (`name`, text, required): What to call the view. Dune requires the name to start with 'result_'. Naming one that already exists updates it rather than creating a second.
- Built from query (`query_id`, text, required): The query whose results the view stores, as its id or its address on dune.com. It has to be a query your account owns.
- Refresh (`refresh_schedule`, text): How often Dune should rebuild the view. Leave it empty and the view only refreshes when something asks it to. One of: `every_15_minutes` (Every 15 minutes (the most often Dune allows)), `every_30_minutes` (Every 30 minutes), `hourly` (Every hour, on the hour), `every_6_hours` (Every 6 hours), `every_12_hours` (Every 12 hours), `daily` (Every day at midnight UTC), `weekly` (Every Monday at midnight UTC), `custom` (Custom: write the cron expression myself).
- Custom schedule (`custom_cron_expression`, text): Only needed when Refresh is set to Custom: a five-field cron expression, at least 15 minutes apart and at most weekly.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Stop refreshing after (`schedule_expires_at`, date and time): When to stop the schedule. Useful for a view that only needs to stay current while something is running. Leave empty to refresh indefinitely.
- Keep it private (`is_private`, true/false): Private views are visible only to your account or team. Default: `false`.

**Outputs**

- `cron_expression` (text): The schedule that was set, if any
- `execution_id` (text): The refresh this started: follow it with Get execution status
- `full_name` (text): The name to write in SQL, when Dune returns it
- `is_private` (true/false): Whether it was made private
- `name` (text): The view's name
- `query_id` (number): The query it is built from
- `query_url` (text): That query's page on dune.com

**Example output**

```json
{
  "cron_expression": "0 * * * *",
  "execution_id": "01HZ065JVE23C23FM2HKWQP2RT",
  "full_name": null,
  "is_private": false,
  "name": "result_daily_volume",
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383"
}
```

### Delete a materialized view

Delete a materialized view, its schedule and the stored table behind it. This cannot be undone, and any query reading the view will stop working. The query the view was built from is left alone.

**Inputs**

- Materialized view (`name`, text, required): The materialized view to act on. Pick one from the list, or type its name: the last part only, which always starts with 'result_'.

**Outputs**

- `deleted` (true/false): Always true when the step succeeds
- `message` (text): Dune's own message
- `name` (text): The view deleted

**Example output**

```json
{
  "deleted": true,
  "message": "Materialized view deleted",
  "name": "result_daily_volume"
}
```

### Delete a table

Delete an uploaded table and everything in it. This cannot be undone, and any query or dashboard reading the table will stop working. To empty a table but keep it queryable, use Clear a table instead.

**Inputs**

- Table (`table`, text, required): The uploaded table to act on. Pick one from the list, or type its name as namespace.table_name (the namespace is your Dune username or team handle).

**Outputs**

- `deleted` (true/false): Always true when the step succeeds
- `full_name` (text): The name it had in SQL
- `message` (text): Dune's own message
- `table` (text): namespace.table_name that was deleted

**Example output**

```json
{
  "deleted": true,
  "full_name": "dune.my_team.interest_rates",
  "message": "Table deleted",
  "table": "my_team.interest_rates"
}
```

### Find tables for a contract

Give a smart contract's address and get back every table Dune has decoded for it: one per event and one per function, each with its real column names. This is how an address becomes something you can write SQL against: paste it in, turn on 'include each table's columns', and the next step can query the contract's activity directly. Costs no credits.

**Inputs**

- Contract address (`contract_address`, text, required): The contract to look up. An EVM address is normalised to lower case, so a checksummed copy from a block explorer works as it is.
- Chains (`blockchains`, list): Only keep tables for these chains, named the way Dune names them (ethereum, base, arbitrum, solana, polygon…). Leave empty for all of them.
- Include each table's columns (`include_schema`, true/false): Bring back the column names and types alongside each match. Turn it on when the next step has to write SQL against what is found; leave it off for a shorter answer. Default: `false`.
- Results per page (`limit`, number): How many tables to bring back, up to 250. From 1 to 250. Default: `50`.
- Skip (`offset`, number): How many results to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk further. At least 0. Default: `0`.

**Outputs**

- `contract_address` (text): The address that was looked up
- `datasets` (list): The tables that matched
- `has_more` (true/false): Whether more matches are waiting
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `returned` (number): Matches in this page
- `table_names` (list): Just the names, ready to drop into SQL
- `total` (number): Matches in total

**Example output**

```json
{
  "contract_address": "0x1f98431c8ad98523631ae4a59f267346ea31f984",
  "datasets": [
    {
      "abi_type": "event",
      "blockchains": [
        "ethereum"
      ],
      "category": "decoded",
      "contract_name": "Pair",
      "dataset_type": "decoded_table",
      "description": "Swap events emitted by Uniswap v3 pairs on Ethereum.",
      "full_name": "uniswap_v3_ethereum.Pair_evt_Swap",
      "owner_scope": "dune",
      "project_name": "uniswap_v3",
      "schema": null,
      "visibility": "public"
    }
  ],
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "returned": 1,
  "table_names": [
    "uniswap_v3_ethereum.Pair_evt_Swap"
  ],
  "total": 1
}
```

### Get a materialized view

One materialized view in detail: the query it is built from, its refresh schedule and next refresh, its size, and the ids of its most recent refreshes, which can be read with Get execution results to see what it last produced. Costs no credits.

**Inputs**

- Materialized view (`name`, text, required): The materialized view to act on. Pick one from the list, or type its name: the last part only, which always starts with 'result_'.

**Outputs**

- `cron_expression` (text): Its refresh schedule, or null if it only refreshes on demand
- `full_name` (text): The name to write in SQL, e.g. dune.my_team.result_daily
- `is_private` (true/false): Whether it is private
- `last_execution_ids` (list): Ids of its most recent refreshes
- `name` (text): The view's name, e.g. result_daily
- `next_refresh_at` (text): When it next refreshes
- `query_id` (number): The query it is built from
- `query_url` (text): That query's page on dune.com
- `schedule_expires_at` (text): When the schedule stops
- `schedule_performance` (text): The engine size its refreshes run on
- `table_size_bytes` (number): Size of the stored result

**Example output**

```json
{
  "cron_expression": "0 * * * *",
  "full_name": "dune.my_team.result_daily_volume",
  "is_private": false,
  "last_execution_ids": [
    "01HKZJ2683PHF9Q9PHHQ8FW4Q1"
  ],
  "name": "result_daily_volume",
  "next_refresh_at": "2026-08-25T10:00:00.000Z",
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "schedule_expires_at": null,
  "schedule_performance": "medium",
  "table_size_bytes": 40960
}
```

### Get a query's latest results

Read the rows a saved query produced the last time it ran, without running it again. This is the cheap way to read Dune on a schedule: let the query refresh itself on Dune's own scheduler and just collect what is there, instead of paying for an execution every time. Works on any public query as well as your own. For a query with parameters, give the values you want and Dune finds the run that used them.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.
- Query parameter values (`query_parameters`, object): Values for the query's parameters, as name/value pairs, for example blockchain: ethereum. Leave a parameter out and Dune uses the default set on the query. Skip this entirely for a query without parameters.

**Outputs**

- `cancelled_at` (text): When it was cancelled, if it was
- `column_names` (list): The result's column names
- `column_types` (list): The result's column types
- `columns` (list): The columns as name/type pairs
- `datapoint_count` (number): Cells returned: what this call is billed on
- `error_message` (text): Why it failed, if it did
- `error_type` (text): Dune's failure type, if it failed
- `execution_ended_at` (text): When it ended
- `execution_id` (text): Id of this run
- `execution_started_at` (text): When it started
- `execution_time_seconds` (number): How long the query took to run
- `expires_at` (text): When the stored result expires
- `failed` (true/false): Whether it finished without producing results
- `first_row` (object): The first row, for a query that returns a single figure
- `has_more` (true/false): Whether more rows are waiting
- `is_finished` (true/false): Whether the run has reached a final state
- `next_offset` (number): Offset to ask for to get the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query that ran, or null for raw SQL
- `query_url` (text): The query's page on dune.com, when it has one
- `result_set_bytes` (number): Bytes in this page
- `row_count` (number): Rows in this page
- `rows` (list): The rows, each an object keyed by column name
- `state` (text): Dune's state constant, e.g. QUERY_STATE_COMPLETED
- `state_label` (text): That state in plain words
- `submitted_at` (text): When the run was submitted
- `succeeded` (true/false): Whether it finished successfully
- `total_result_set_bytes` (number): Bytes in the whole result
- `total_row_count` (number): How many rows the whole result has

**Example output**

```json
{
  "cancelled_at": null,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "column_types": [
    "timestamp",
    "varchar",
    "double"
  ],
  "columns": [
    {
      "name": "block_date",
      "type": "timestamp"
    },
    {
      "name": "project",
      "type": "varchar"
    },
    {
      "name": "volume_usd",
      "type": "double"
    }
  ],
  "datapoint_count": 6,
  "error_message": null,
  "error_type": null,
  "execution_ended_at": "2026-08-25T09:14:11.884Z",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "execution_started_at": "2026-08-25T09:14:03.010Z",
  "execution_time_seconds": 8.874,
  "expires_at": "2026-11-23T09:14:11.884Z",
  "failed": false,
  "first_row": {
    "block_date": "2026-08-25 00:00:00.000 UTC",
    "project": "uniswap",
    "volume_usd": 1843992104.51
  },
  "has_more": false,
  "is_finished": true,
  "next_offset": null,
  "offset": 0,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "result_set_bytes": 214,
  "row_count": 2,
  "rows": [
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "uniswap",
      "volume_usd": 1843992104.51
    },
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "curve",
      "volume_usd": 412887320.09
    }
  ],
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "submitted_at": "2026-08-25T09:14:02.221Z",
  "succeeded": true,
  "total_result_set_bytes": 214,
  "total_row_count": 2
}
```

### Get a query's latest results as CSV

The same rows as Get a query's latest results, but as CSV text: ready to write to a file, attach to an email or paste into a spreadsheet. The cheapest way to put a Dune dashboard's numbers somewhere else on a schedule.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.

**Outputs**

- `bytes` (number): Size of the CSV text
- `column_names` (list): The header row, split up
- `csv` (text): The rows as CSV text, header first
- `execution_id` (text): Id of the run, when read by run
- `has_more` (true/false): Whether another page may exist
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query, when read by query
- `query_url` (text): The query's page on dune.com
- `row_count` (number): Rows of data, not counting the header

**Example output**

```json
{
  "bytes": 118,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "csv": "block_date,project,volume_usd\n2026-08-25 00:00:00.000 UTC,uniswap,1843992104.51\n2026-08-25 00:00:00.000 UTC,curve,412887320.09\n",
  "execution_id": null,
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "row_count": 2
}
```

### Get a query's pipeline

See what a query actually depends on before you run it: every materialized view feeding it, and the order they run in. Use it to understand a query someone else built, to work out what a pipeline run will cost, or to find the views worth refreshing on their own schedule.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Query parameter values (`query_parameters`, object): Values for the query's parameters, as name/value pairs, for example blockchain: ethereum. Leave a parameter out and Dune uses the default set on the query. Skip this entirely for a query without parameters.

**Outputs**

- `materialized_views` (list): Names of the views the query depends on
- `node_count` (number): How many steps
- `nodes` (list): The steps, in dependency order
- `pipeline` (object): Dune's own pipeline definition, unchanged
- `query_id` (number): The query asked about
- `query_ids` (list): Ids of the queries in the pipeline
- `query_url` (text): Its page on dune.com

**Example output**

```json
{
  "materialized_views": [
    "dune.my_team.result_base_data"
  ],
  "node_count": 2,
  "nodes": [
    {
      "depends_on": [],
      "id": 1,
      "kind": "materialized_view",
      "materialized_view": "dune.my_team.result_base_data",
      "performance": "medium",
      "query_id": null
    },
    {
      "depends_on": [
        1
      ],
      "id": 2,
      "kind": "query",
      "materialized_view": null,
      "performance": "medium",
      "query_id": 1215383
    }
  ],
  "pipeline": {
    "nodes": []
  },
  "query_id": 1215383,
  "query_ids": [
    1215383
  ],
  "query_url": "https://dune.com/queries/1215383"
}
```

### Get a table's columns

Look up one table by name and get its columns, their types and what each one holds. Put it before Run SQL to write a statement against the real column names instead of guessing at them. Costs no credits.

**Inputs**

- Table (`slug`, text, required): The table's full name, as you would write it in SQL.

**Outputs**

- `column_count` (number): How many columns it has
- `columns` (list): Its columns
- `created_at` (text): When it was created
- `full_name` (text): The name to write in SQL
- `is_private` (true/false): Whether it is private
- `owner_handle` (text): Who owns it
- `owner_type` (text): Whether that is a user or a team
- `slug` (text): The name asked about
- `type` (text): What kind of table it is
- `updated_at` (text): When it last changed

**Example output**

```json
{
  "column_count": 3,
  "columns": [
    {
      "description": "When the trade was included in a block",
      "name": "block_time",
      "nullable": false,
      "type": "timestamp"
    },
    {
      "description": "The DEX the trade happened on",
      "name": "project",
      "nullable": false,
      "type": "varchar"
    },
    {
      "description": "Trade size in US dollars",
      "name": "amount_usd",
      "nullable": true,
      "type": "double"
    }
  ],
  "created_at": "2023-02-14T10:02:11.000Z",
  "full_name": "dex.trades",
  "is_private": false,
  "owner_handle": "dune",
  "owner_type": "team",
  "slug": "dex.trades",
  "type": "spell",
  "updated_at": "2026-08-25T05:00:00.000Z"
}
```

### Get credit usage

How many credits this Dune account has used and has left this billing period, plus how much of its storage allowance is taken. Credits are what a Dune workflow actually spends (the Free plan comes with 2,500 a month), so this is the check to put at the top of an expensive scheduled workflow, or on its own schedule to warn someone before the month runs out. Costs no credits itself.

**Inputs**

- From (`start_date`, date): Only report billing periods from this date onwards. Leave both dates empty for the current period.
- To (`end_date`, date): Only report billing periods up to this date.

**Outputs**

- `billing_periods` (list): One entry per billing period
- `bytes_allowed` (number): Storage the plan allows
- `bytes_used` (number): Storage used
- `credits_included` (number): Credits the plan includes
- `credits_remaining` (number): Credits left: the number to branch on
- `credits_used` (number): Credits used in the newest period
- `current_period_end` (text): When it ends
- `current_period_start` (text): When the newest period began
- `percent_used` (number): How much of the allowance is gone
- `period_count` (number): How many periods were reported
- `private_dashboards` (number): Private dashboards on the account
- `private_queries` (number): Private queries on the account
- `storage_percent_used` (number): How full the storage allowance is

**Example output**

```json
{
  "billing_periods": [
    {
      "credits_included": 2500,
      "credits_remaining": 2081.5,
      "credits_used": 418.5,
      "end_date": "2026-09-01",
      "percent_used": 16.74,
      "start_date": "2026-08-01"
    }
  ],
  "bytes_allowed": 104857600,
  "bytes_used": 115262,
  "credits_included": 2500,
  "credits_remaining": 2081.5,
  "credits_used": 418.5,
  "current_period_end": "2026-09-01",
  "current_period_start": "2026-08-01",
  "percent_used": 16.74,
  "period_count": 1,
  "private_dashboards": 0,
  "private_queries": 0,
  "storage_percent_used": 0.11
}
```

### Get execution results

Collect the rows a finished run produced, using the execution id from a step that started it. Results stay on Dune for 90 days, so the same execution can be read as many times as you like without running the query again. Use the row, skip, column, filter and ordering options to walk a large result a page at a time, or to pull only the part you need.

**Inputs**

- Execution (`execution_id`, text, required): The execution to read, as returned by a step that started one (Run a saved query, Run SQL, Start a query run, Start a SQL run, or a materialized view refresh).
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.

**Outputs**

- `cancelled_at` (text): When it was cancelled, if it was
- `column_names` (list): The result's column names
- `column_types` (list): The result's column types
- `columns` (list): The columns as name/type pairs
- `datapoint_count` (number): Cells returned: what this call is billed on
- `error_message` (text): Why it failed, if it did
- `error_type` (text): Dune's failure type, if it failed
- `execution_ended_at` (text): When it ended
- `execution_id` (text): Id of this run
- `execution_started_at` (text): When it started
- `execution_time_seconds` (number): How long the query took to run
- `expires_at` (text): When the stored result expires
- `failed` (true/false): Whether it finished without producing results
- `first_row` (object): The first row, for a query that returns a single figure
- `has_more` (true/false): Whether more rows are waiting
- `is_finished` (true/false): Whether the run has reached a final state
- `next_offset` (number): Offset to ask for to get the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query that ran, or null for raw SQL
- `query_url` (text): The query's page on dune.com, when it has one
- `result_set_bytes` (number): Bytes in this page
- `row_count` (number): Rows in this page
- `rows` (list): The rows, each an object keyed by column name
- `state` (text): Dune's state constant, e.g. QUERY_STATE_COMPLETED
- `state_label` (text): That state in plain words
- `submitted_at` (text): When the run was submitted
- `succeeded` (true/false): Whether it finished successfully
- `total_result_set_bytes` (number): Bytes in the whole result
- `total_row_count` (number): How many rows the whole result has

**Example output**

```json
{
  "cancelled_at": null,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "column_types": [
    "timestamp",
    "varchar",
    "double"
  ],
  "columns": [
    {
      "name": "block_date",
      "type": "timestamp"
    },
    {
      "name": "project",
      "type": "varchar"
    },
    {
      "name": "volume_usd",
      "type": "double"
    }
  ],
  "datapoint_count": 6,
  "error_message": null,
  "error_type": null,
  "execution_ended_at": "2026-08-25T09:14:11.884Z",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "execution_started_at": "2026-08-25T09:14:03.010Z",
  "execution_time_seconds": 8.874,
  "expires_at": "2026-11-23T09:14:11.884Z",
  "failed": false,
  "first_row": {
    "block_date": "2026-08-25 00:00:00.000 UTC",
    "project": "uniswap",
    "volume_usd": 1843992104.51
  },
  "has_more": false,
  "is_finished": true,
  "next_offset": null,
  "offset": 0,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "result_set_bytes": 214,
  "row_count": 2,
  "rows": [
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "uniswap",
      "volume_usd": 1843992104.51
    },
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "curve",
      "volume_usd": 412887320.09
    }
  ],
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "submitted_at": "2026-08-25T09:14:02.221Z",
  "succeeded": true,
  "total_result_set_bytes": 214,
  "total_row_count": 2
}
```

### Get execution results as CSV

The same rows as Get execution results, but as CSV text rather than a list of objects: ready to write to a file, attach to an email or paste into a spreadsheet. The header row comes back split out separately as well, so a later step can see the column names without parsing the text.

**Inputs**

- Execution (`execution_id`, text, required): The execution to read, as returned by a step that started one (Run a saved query, Run SQL, Start a query run, Start a SQL run, or a materialized view refresh).
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.

**Outputs**

- `bytes` (number): Size of the CSV text
- `column_names` (list): The header row, split up
- `csv` (text): The rows as CSV text, header first
- `execution_id` (text): Id of the run, when read by run
- `has_more` (true/false): Whether another page may exist
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query, when read by query
- `query_url` (text): The query's page on dune.com
- `row_count` (number): Rows of data, not counting the header

**Example output**

```json
{
  "bytes": 118,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "csv": "block_date,project,volume_usd\n2026-08-25 00:00:00.000 UTC,uniswap,1843992104.51\n2026-08-25 00:00:00.000 UTC,curve,412887320.09\n",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "query_id": null,
  "query_url": null,
  "row_count": 2
}
```

### Get execution status

Check on a run that was started earlier: whether it is queued, running or finished, how many rows it produced, how long it took and how many credits it cost. This is the step to branch a workflow on ('is finished' and 'succeeded' come back as plain true/false), and it costs no credits itself, so a scheduled workflow can poll it freely.

**Inputs**

- Execution (`execution_id`, text, required): The execution to read, as returned by a step that started one (Run a saved query, Run SQL, Start a query run, Start a SQL run, or a materialized view refresh).

**Outputs**

- `cancelled_at` (text): When it was cancelled, if it was
- `column_names` (list): The result's column names
- `column_types` (list): The result's column types
- `columns` (list): The columns as name/type pairs
- `datapoint_count` (number): Cells returned: what this call is billed on
- `error_message` (text): Why it failed, if it did
- `error_type` (text): Dune's failure type, if it failed
- `execution_cost_credits` (number): Credits the run has consumed
- `execution_ended_at` (text): When it ended
- `execution_id` (text): Id of this run
- `execution_started_at` (text): When it started
- `execution_time_seconds` (number): How long the query took to run
- `expires_at` (text): When the stored result expires
- `failed` (true/false): Whether it finished without producing results
- `is_finished` (true/false): Whether the run has reached a final state
- `query_id` (number): Id of the query that ran, or null for raw SQL
- `query_url` (text): The query's page on dune.com, when it has one
- `queue_position` (number): Place in the queue, while it is waiting
- `result_set_bytes` (number): Bytes in this page
- `state` (text): Dune's state constant, e.g. QUERY_STATE_COMPLETED
- `state_label` (text): That state in plain words
- `submitted_at` (text): When the run was submitted
- `succeeded` (true/false): Whether it finished successfully
- `total_result_set_bytes` (number): Bytes in the whole result
- `total_row_count` (number): How many rows the whole result has

**Example output**

```json
{
  "cancelled_at": null,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "column_types": [
    "timestamp",
    "varchar",
    "double"
  ],
  "columns": [
    {
      "name": "block_date",
      "type": "timestamp"
    },
    {
      "name": "project",
      "type": "varchar"
    },
    {
      "name": "volume_usd",
      "type": "double"
    }
  ],
  "datapoint_count": 6,
  "error_message": null,
  "error_type": null,
  "execution_cost_credits": 12,
  "execution_ended_at": "2026-08-25T09:14:11.884Z",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "execution_started_at": "2026-08-25T09:14:03.010Z",
  "execution_time_seconds": 8.874,
  "expires_at": "2026-11-23T09:14:11.884Z",
  "failed": false,
  "is_finished": true,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "queue_position": null,
  "result_set_bytes": 214,
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "submitted_at": "2026-08-25T09:14:02.221Z",
  "succeeded": true,
  "total_result_set_bytes": 214,
  "total_row_count": 2
}
```

### Get pipeline status

Check on a pipeline run, step by step: which have finished, which failed and why, and the execution id each produced so its rows can be collected with Get execution results. Costs no credits, so a scheduled workflow can poll it freely.

**Inputs**

- Pipeline execution (`pipeline_execution_id`, text, required): The pipeline run to check, as returned by Run a pipeline or Run a query with its pipeline.

**Outputs**

- `error_message` (text): Why the pipeline failed, if it did
- `execution_ids` (list): Every execution the pipeline produced
- `is_finished` (true/false): Whether every step has finished
- `node_count` (number): How many steps
- `nodes` (list): One entry per step
- `pipeline_execution_id` (text): The pipeline run being checked
- `state` (text): Dune's state constant
- `state_label` (text): That state in plain words
- `succeeded` (true/false): Whether every step finished successfully

**Example output**

```json
{
  "error_message": null,
  "execution_ids": [
    "01HKZJ2683PHF9Q9PHHQ8FW4Q1"
  ],
  "is_finished": true,
  "node_count": 1,
  "nodes": [
    {
      "error_message": null,
      "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
      "id": 1,
      "kind": "materialized_view",
      "materialized_view": "dune.my_team.result_base_data",
      "query_id": null,
      "state": "QUERY_STATE_COMPLETED",
      "state_label": "Completed",
      "succeeded": true
    }
  ],
  "pipeline_execution_id": "01HZABC1230000000000000000",
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "succeeded": true
}
```

### Insert rows

Append rows to a table that Create a table made. Rows go up as a list of objects (the same shape an earlier step produces), keyed by column name, so a workflow can carry data straight from another system into Dune without building a file. Rows are added to what is already there rather than replacing it, and either every row in the step lands or none does.

**Inputs**

- Table (`table`, text, required): The uploaded table to act on. Pick one from the list, or type its name as namespace.table_name (the namespace is your Dune username or team handle).
- Rows (`rows`, list): The rows to add, as a list of objects: one object per row, its keys matching the table's column names.
- Or CSV instead (`csv_data`, text): CSV text to append instead of rows, with the column names on the first line. Use it when the data is already a CSV file; otherwise fill in Rows above.

**Outputs**

- `bytes_written` (number): Bytes stored: what the write is billed on
- `format` (text): 'json' for rows, 'csv' for CSV text
- `full_name` (text): The name to write in SQL
- `rows_sent` (number): Rows in the request
- `rows_written` (number): Rows Dune reports it stored
- `table` (text): namespace.table_name that was written to

**Example output**

```json
{
  "bytes_written": 96,
  "format": "json",
  "full_name": "dune.my_team.interest_rates",
  "rows_sent": 2,
  "rows_written": 2,
  "table": "my_team.interest_rates"
}
```

### List materialized views

Every materialized view this account owns: the query behind each one, how often it refreshes, when it next will, and how much storage it is using. Costs no credits.

**Inputs**

- Views per page (`limit`, number): How many views to bring back. From 1 to 10000. Default: `50`.
- Skip (`offset`, number): How many results to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk further. At least 0. Default: `0`.

**Outputs**

- `has_more` (true/false): Whether more views are waiting
- `materialized_views` (list): The views
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `returned` (number): Views in this page
- `total_size_bytes` (number): Storage the views in this page take up
- `view_names` (list): Just the names

**Example output**

```json
{
  "has_more": false,
  "materialized_views": [
    {
      "cron_expression": "0 * * * *",
      "full_name": "dune.my_team.result_daily_volume",
      "is_private": false,
      "last_execution_ids": [
        "01HKZJ2683PHF9Q9PHHQ8FW4Q1"
      ],
      "name": "result_daily_volume",
      "next_refresh_at": "2026-08-25T10:00:00.000Z",
      "query_id": 1215383,
      "query_url": "https://dune.com/queries/1215383",
      "schedule_expires_at": null,
      "schedule_performance": "medium",
      "table_size_bytes": 40960
    }
  ],
  "next_offset": null,
  "offset": 0,
  "returned": 1,
  "total_size_bytes": 40960,
  "view_names": [
    "result_daily_volume"
  ]
}
```

### List tables

Walk Dune's table catalogue a page at a time, optionally narrowed to one owner or to certain kinds of table. Use it to audit what your team has published, or to build a catalogue of your own; Search tables is the better step when you know what you are looking for. Costs no credits.

**Inputs**

- Owned by (`owner_handle`, text): Only keep tables owned by this Dune username or team handle. Leave empty for everyone's. Dune only lets an owner be combined with the table types somebody can actually own, so pair it with uploaded table: data someone uploaded, materialized view: a query's results, stored, transformation table, transformation view below, or with no type at all.
- Table types (`dataset_types`, list): Only keep tables of these types. Choose none for all of them. Alongside an owner above, only uploaded table: data someone uploaded, materialized view: a query's results, stored, transformation table, transformation view can be asked for; the rest belong to no one. One or more of: `dune_table` (Dune table: raw chain data), `decoded_table` (Decoded table: a contract's events and calls), `spell` (Spell: a community-curated model), `uploaded_table` (Uploaded table: data someone uploaded), `materialized_view` (Materialized view: a query's results, stored), `transformation_table` (Transformation table), `transformation_view` (Transformation view).
- Results per page (`limit`, number): How many tables to bring back, up to 250. From 1 to 250. Default: `50`.
- Skip (`offset`, number): How many results to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk further. At least 0. Default: `0`.

**Outputs**

- `datasets` (list): The tables that matched
- `has_more` (true/false): Whether more matches are waiting
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `returned` (number): Matches in this page
- `table_names` (list): Just the names, ready to drop into SQL
- `total` (number): Matches in total

**Example output**

```json
{
  "datasets": [
    {
      "column_count": 2,
      "columns": [
        {
          "description": null,
          "name": "day",
          "nullable": false,
          "type": "timestamp"
        },
        {
          "description": null,
          "name": "dgs10",
          "nullable": true,
          "type": "double"
        }
      ],
      "created_at": "2026-05-15T20:34:58.585Z",
      "full_name": "dune.my_team.interest_rates",
      "is_private": false,
      "owner_handle": "my_team",
      "owner_type": "team",
      "type": "uploaded_table",
      "updated_at": "2026-08-16T21:19:02.459Z"
    }
  ],
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "returned": 1,
  "table_names": [
    "dune.my_team.interest_rates"
  ],
  "total": 1
}
```

### List uploaded tables

Everything this Dune account has uploaded: each table's name, columns, size and when it last changed. Use it to see what is taking up the plan's storage allowance (100MB on the Free plan), or to find the name of a table for a later step. Costs no credits.

**Inputs**

- Tables per page (`limit`, number): How many tables to bring back. From 1 to 10000. Default: `50`.
- Skip (`offset`, number): How many results to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk further. At least 0. Default: `0`.

**Outputs**

- `has_more` (true/false): Whether more tables are waiting
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `returned` (number): Tables in this page
- `table_names` (list): Just the namespace.table_name values
- `tables` (list): The uploaded tables
- `total_size_bytes` (number): Total size of the tables in this page

**Example output**

```json
{
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "returned": 1,
  "table_names": [
    "my_team.interest_rates"
  ],
  "tables": [
    {
      "column_count": 2,
      "columns": [
        {
          "name": "day",
          "nullable": false,
          "type": "timestamp"
        },
        {
          "name": "dgs10",
          "nullable": true,
          "type": "double"
        }
      ],
      "created_at": "2026-05-15T20:34:58.585Z",
      "full_name": "dune.my_team.interest_rates",
      "is_private": false,
      "name": "my_team.interest_rates",
      "owner_handle": "my_team",
      "owner_type": "team",
      "purged_at": null,
      "table_size_bytes": 115262,
      "updated_at": "2026-08-16T21:19:02.459Z"
    }
  ],
  "total_size_bytes": 115262
}
```

### Refresh a materialized view

Rebuild a materialized view now, instead of waiting for its schedule. Use it when something upstream has just changed and the next thing to read the view needs the new numbers. Returns the refresh's execution id, so a later step can wait for it with Get execution status.

**Inputs**

- Materialized view (`name`, text, required): The materialized view to act on. Pick one from the list, or type its name: the last part only, which always starts with 'result_'.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).

**Outputs**

- `execution_id` (text): The refresh that was started
- `full_name` (text): The name to write in SQL
- `name` (text): The view refreshed
- `performance` (text): The engine size it runs on

**Example output**

```json
{
  "execution_id": "01HZ065JVE23C23FM2HKWQP2RT",
  "full_name": "dune.my_team.result_daily_volume",
  "name": "result_daily_volume",
  "performance": "medium"
}
```

### Run a pipeline

Run several queries and materialized view refreshes together, in an order you define. Each step names either a query or a view, and lists the steps it has to wait for; Dune runs everything that can run at once and holds back the rest. Use it to rebuild a set of related tables in the right order in a single call. For the common case (one query and whatever it depends on), Run a query with its pipeline works this out for you.

**Inputs**

- Steps (`nodes`, list, required): The steps to run, as a list of objects. Each one needs an 'id' (a number you choose), and either a 'query_id' or a 'materialized_view' name. Add 'depends_on' with the ids it has to wait for, and 'performance' to set its engine size.

**Outputs**

- `node_count` (number): Steps submitted
- `nodes` (list): The steps, as Dune received them
- `pipeline_execution_id` (text): Id to follow with Get pipeline status

**Example output**

```json
{
  "node_count": 2,
  "nodes": [
    {
      "depends_on": [],
      "id": 1,
      "kind": "materialized_view",
      "materialized_view": "result_daily_volume",
      "performance": null,
      "query_id": null
    },
    {
      "depends_on": [
        1
      ],
      "id": 2,
      "kind": "query",
      "materialized_view": null,
      "performance": null,
      "query_id": 1215383
    }
  ],
  "pipeline_execution_id": "01HZABC1230000000000000000"
}
```

### Run a query with its pipeline

Run a query together with everything it is built on, as one unit: Dune refreshes each materialized view the query depends on, in dependency order, then runs the query itself. Use it when the query reads views that would otherwise be stale; it is the difference between a fresh number and yesterday's. Returns a pipeline execution id to follow with Get pipeline status.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Query parameter values (`query_parameters`, object): Values for the query's parameters, as name/value pairs, for example blockchain: ethereum. Leave a parameter out and Dune uses the default set on the query. Skip this entirely for a query without parameters.

**Outputs**

- `pipeline_execution_id` (text): Id to follow with Get pipeline status
- `query_id` (number): The query that ran
- `query_url` (text): Its page on dune.com

**Example output**

```json
{
  "pipeline_execution_id": "01HZABC1230000000000000000",
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383"
}
```

### Run a saved query

Run a query saved on Dune and get its rows back in one step. Running a query on Dune is normally three calls (start it, watch it, collect it), and this does all three: it submits the run, waits for it to finish, and returns the rows, the columns and what it cost in credits. Give it the query's address from dune.com, fill in any parameters the query takes, and narrow the result with the row, column, filter and ordering options so you only pay for the data you actually use. If the query is still running when the wait runs out, the step still succeeds and hands back the execution id for a later step to collect.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Query parameter values (`query_parameters`, object): Values for the query's parameters, as name/value pairs, for example blockchain: ethereum. Leave a parameter out and Dune uses the default set on the query. Skip this entirely for a query without parameters.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.
- Wait up to (seconds) (`wait_seconds`, number): How long to wait for the run to finish before handing back. If the run is still going when this runs out the step still succeeds, returning the execution id so a later step can collect the rows with Get execution results. From 0 to 900. Default: `300`.

**Outputs**

- `cancelled_at` (text): When it was cancelled, if it was
- `column_names` (list): The result's column names
- `column_types` (list): The result's column types
- `columns` (list): The columns as name/type pairs
- `datapoint_count` (number): Cells returned: what this call is billed on
- `error_message` (text): Why it failed, if it did
- `error_type` (text): Dune's failure type, if it failed
- `execution_cost_credits` (number): Credits the run consumed
- `execution_ended_at` (text): When it ended
- `execution_id` (text): Id of this run
- `execution_started_at` (text): When it started
- `execution_time_seconds` (number): How long the query took to run
- `expires_at` (text): When the stored result expires
- `failed` (true/false): Whether it finished without producing results
- `first_row` (object): The first row, for a query that returns a single figure
- `has_more` (true/false): Whether more rows are waiting
- `is_finished` (true/false): Whether the run has reached a final state
- `next_offset` (number): Offset to ask for to get the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query that ran, or null for raw SQL
- `query_url` (text): The query's page on dune.com, when it has one
- `queue_position` (number): Place in the queue, while the run is still waiting
- `result_set_bytes` (number): Bytes in this page
- `row_count` (number): Rows in this page
- `rows` (list): The rows, each an object keyed by column name
- `state` (text): Dune's state constant, e.g. QUERY_STATE_COMPLETED
- `state_label` (text): That state in plain words
- `submitted_at` (text): When the run was submitted
- `succeeded` (true/false): Whether it finished successfully
- `timed_out` (true/false): True when the wait ran out before the run finished
- `total_result_set_bytes` (number): Bytes in the whole result
- `total_row_count` (number): How many rows the whole result has
- `wait_seconds` (number): How long the step waited

**Example output**

```json
{
  "cancelled_at": null,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "column_types": [
    "timestamp",
    "varchar",
    "double"
  ],
  "columns": [
    {
      "name": "block_date",
      "type": "timestamp"
    },
    {
      "name": "project",
      "type": "varchar"
    },
    {
      "name": "volume_usd",
      "type": "double"
    }
  ],
  "datapoint_count": 6,
  "error_message": null,
  "error_type": null,
  "execution_cost_credits": 12,
  "execution_ended_at": "2026-08-25T09:14:11.884Z",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "execution_started_at": "2026-08-25T09:14:03.010Z",
  "execution_time_seconds": 8.874,
  "expires_at": "2026-11-23T09:14:11.884Z",
  "failed": false,
  "first_row": {
    "block_date": "2026-08-25 00:00:00.000 UTC",
    "project": "uniswap",
    "volume_usd": 1843992104.51
  },
  "has_more": false,
  "is_finished": true,
  "next_offset": null,
  "offset": 0,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "queue_position": null,
  "result_set_bytes": 214,
  "row_count": 2,
  "rows": [
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "uniswap",
      "volume_usd": 1843992104.51
    },
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "curve",
      "volume_usd": 412887320.09
    }
  ],
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "submitted_at": "2026-08-25T09:14:02.221Z",
  "succeeded": true,
  "timed_out": false,
  "total_result_set_bytes": 214,
  "total_row_count": 2,
  "wait_seconds": 300
}
```

### Run SQL

Write DuneSQL and get the answer back, without saving a query first. Dune's warehouse holds decoded data for 100+ chains (blocks, transactions, logs, token transfers, prices, NFT trades and the community's curated tables on top of them), and this runs a statement straight against it, waits for it, and returns the rows. Use Search tables first if you don't know what a table is called. Note that Dune charges for the compute a statement uses, so filter by time and select only the columns you need.

**Inputs**

- SQL (`sql`, text, required): The DuneSQL to run. Dune's SQL is Trino-flavoured: single quotes for text, double quotes for column names that need them, and interval arithmetic for dates.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Rows to return (`limit`, number): How many rows to bring back in this step. Results are charged by the cell, so asking for what you need rather than everything is what keeps a workflow inside its credit allowance. From 1 to 50000. Default: `1000`.
- Skip (`offset`, number): How many rows to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk a large result one page at a time. At least 0. Default: `0`.
- Only these columns (`columns`, list): Bring back only these columns instead of all of them. Cheapest way to cut the cost of a wide result: name the five columns you need rather than paying for fifty. Leave empty for every column.
- Only rows where (`filters`, text): Keep only the rows matching this condition, written like a SQL WHERE clause: quote text values, leave numbers unquoted, and combine with AND / OR / IN / LIKE. Dune applies it before sending, so it costs less than filtering afterwards. Literal values only: no now() or interval arithmetic, and no NOT IN or NOT LIKE.
- Order by (`sort_by`, text): How to order the rows, written like a SQL ORDER BY clause: a column name, 'desc' after it for largest first, and commas between several.
- Random sample of (`sample_count`, number): Instead of a page, take this many rows at random from across the whole result, useful for a spot check of a result too big to read. A sample has no pages, so the rows-to-return and skip options above are ignored when this is set; clear the filter first, because filtering and sampling cannot be combined. From 1 to 50000.
- Accept a truncated result (`allow_partial_results`, true/false): Dune stores at most 32GB per result and refuses to serve one that was cut short. Turn this on to take the part that was kept rather than failing the step. Default: `false`.
- Wait up to (seconds) (`wait_seconds`, number): How long to wait for the run to finish before handing back. If the run is still going when this runs out the step still succeeds, returning the execution id so a later step can collect the rows with Get execution results. From 0 to 900. Default: `300`.

**Outputs**

- `cancelled_at` (text): When it was cancelled, if it was
- `column_names` (list): The result's column names
- `column_types` (list): The result's column types
- `columns` (list): The columns as name/type pairs
- `datapoint_count` (number): Cells returned: what this call is billed on
- `error_message` (text): Why it failed, if it did
- `error_type` (text): Dune's failure type, if it failed
- `execution_cost_credits` (number): Credits the run consumed
- `execution_ended_at` (text): When it ended
- `execution_id` (text): Id of this run
- `execution_started_at` (text): When it started
- `execution_time_seconds` (number): How long the query took to run
- `expires_at` (text): When the stored result expires
- `failed` (true/false): Whether it finished without producing results
- `first_row` (object): The first row, for a query that returns a single figure
- `has_more` (true/false): Whether more rows are waiting
- `is_finished` (true/false): Whether the run has reached a final state
- `next_offset` (number): Offset to ask for to get the next page
- `offset` (number): The offset this page started at
- `query_id` (number): Id of the query that ran, or null for raw SQL
- `query_url` (text): The query's page on dune.com, when it has one
- `queue_position` (number): Place in the queue, while the run is still waiting
- `result_set_bytes` (number): Bytes in this page
- `row_count` (number): Rows in this page
- `rows` (list): The rows, each an object keyed by column name
- `sql` (text): The statement that ran
- `state` (text): Dune's state constant, e.g. QUERY_STATE_COMPLETED
- `state_label` (text): That state in plain words
- `submitted_at` (text): When the run was submitted
- `succeeded` (true/false): Whether it finished successfully
- `timed_out` (true/false): True when the wait ran out before the run finished
- `total_result_set_bytes` (number): Bytes in the whole result
- `total_row_count` (number): How many rows the whole result has
- `wait_seconds` (number): How long the step waited

**Example output**

```json
{
  "cancelled_at": null,
  "column_names": [
    "block_date",
    "project",
    "volume_usd"
  ],
  "column_types": [
    "timestamp",
    "varchar",
    "double"
  ],
  "columns": [
    {
      "name": "block_date",
      "type": "timestamp"
    },
    {
      "name": "project",
      "type": "varchar"
    },
    {
      "name": "volume_usd",
      "type": "double"
    }
  ],
  "datapoint_count": 6,
  "error_message": null,
  "error_type": null,
  "execution_cost_credits": 12,
  "execution_ended_at": "2026-08-25T09:14:11.884Z",
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "execution_started_at": "2026-08-25T09:14:03.010Z",
  "execution_time_seconds": 8.874,
  "expires_at": "2026-11-23T09:14:11.884Z",
  "failed": false,
  "first_row": {
    "block_date": "2026-08-25 00:00:00.000 UTC",
    "project": "uniswap",
    "volume_usd": 1843992104.51
  },
  "has_more": false,
  "is_finished": true,
  "next_offset": null,
  "offset": 0,
  "query_id": null,
  "query_url": null,
  "queue_position": null,
  "result_set_bytes": 214,
  "row_count": 2,
  "rows": [
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "uniswap",
      "volume_usd": 1843992104.51
    },
    {
      "block_date": "2026-08-25 00:00:00.000 UTC",
      "project": "curve",
      "volume_usd": 412887320.09
    }
  ],
  "sql": "select block_date, project, sum(amount_usd) as volume_usd from dex.trades group by 1, 2",
  "state": "QUERY_STATE_COMPLETED",
  "state_label": "Completed",
  "submitted_at": "2026-08-25T09:14:02.221Z",
  "succeeded": true,
  "timed_out": false,
  "total_result_set_bytes": 214,
  "total_row_count": 2,
  "wait_seconds": 300
}
```

### Search tables

Find the table to query. Dune's catalogue holds tens of thousands of them (raw chain data, decoded contract events, curated cross-protocol models and everything the community has uploaded), and this searches it in plain language, narrowed by chain, by kind of table and by who maintains it. This is the step to put before Run SQL when you don't already know what something is called: turn on 'include each table's columns' and the next step has the column names to write against. Costs no credits.

**Inputs**

- Search for (`query`, text): What to look for, in plain words: a subject, a protocol or a table name. Leave it empty to browse by the filters alone.
- Kinds of table (`categories`, list): Only keep tables in these categories. Choose none to search all of them. One or more of: `canonical` (Canonical: Dune's own chain tables), `decoded` (Decoded: smart contract events and calls), `spell` (Spell: curated cross-protocol models), `community` (Community: tables people have uploaded or built).
- Chains (`blockchains`, list): Only keep tables for these chains, named the way Dune names them (ethereum, base, arbitrum, solana, polygon…). Leave empty for all of them.
- Table types (`dataset_types`, list): Only keep tables of these types. A finer filter than the categories above; choose none for all of them. One or more of: `dune_table` (Dune table: raw chain data), `decoded_table` (Decoded table: a contract's events and calls), `spell` (Spell: a community-curated model), `uploaded_table` (Uploaded table: data someone uploaded), `materialized_view` (Materialized view: a query's results, stored), `transformation_table` (Transformation table), `transformation_view` (Transformation view).
- Whose tables (`owner_scope`, text): Narrow the search to the tables your own account or your team owns. Leave empty to search everyone's. One of: `all` (Everyone: Dune's tables and the community's), `me` (Mine: tables my own account owns), `team` (My team's: tables my team owns).
- Include each table's columns (`include_schema`, true/false): Bring back the column names and types alongside each match. Turn it on when the next step has to write SQL against what is found; leave it off for a shorter answer. Default: `false`.
- Include my private tables (`include_private`, true/false): Also search the tables only your account can see. Default: `false`.
- Results per page (`limit`, number): How many tables to bring back, up to 250. From 1 to 250. Default: `50`.
- Skip (`offset`, number): How many results to skip before returning any: 0 for the first page. Use the 'next offset' a previous step returned to walk further. At least 0. Default: `0`.

**Outputs**

- `datasets` (list): The tables that matched
- `has_more` (true/false): Whether more matches are waiting
- `next_offset` (number): Offset for the next page
- `offset` (number): The offset this page started at
- `query` (text): The search that ran
- `returned` (number): Matches in this page
- `table_names` (list): Just the names, ready to drop into SQL
- `total` (number): Matches in total

**Example output**

```json
{
  "datasets": [
    {
      "abi_type": null,
      "blockchains": [
        "ethereum",
        "base",
        "arbitrum"
      ],
      "category": "spell",
      "contract_name": null,
      "dataset_type": "spell",
      "description": "Every DEX trade Dune decodes, across every chain.",
      "full_name": "dex.trades",
      "owner_scope": "dune",
      "project_name": null,
      "schema": null,
      "visibility": "public"
    },
    {
      "abi_type": "event",
      "blockchains": [
        "ethereum"
      ],
      "category": "decoded",
      "contract_name": "Pair",
      "dataset_type": "decoded_table",
      "description": "Swap events emitted by Uniswap v3 pairs on Ethereum.",
      "full_name": "uniswap_v3_ethereum.Pair_evt_Swap",
      "owner_scope": "dune",
      "project_name": "uniswap_v3",
      "schema": null,
      "visibility": "public"
    }
  ],
  "has_more": false,
  "next_offset": null,
  "offset": 0,
  "query": "dex trades",
  "returned": 2,
  "table_names": [
    "dex.trades",
    "uniswap_v3_ethereum.Pair_evt_Swap"
  ],
  "total": 2
}
```

### Start a query run

Start a saved query running and return straight away with its execution id, without waiting for the rows. Use this for a query too slow to hold a workflow open on: start it here, and let a later step, or a scheduled run an hour from now, check it with Get execution status and collect it with Get execution results. For everything else, Run a saved query does all of it in one step.

**Inputs**

- Query (`query_id`, text, required): The query to run, as its id or its address on dune.com. Open the query on Dune and either copy the whole address from the browser bar or take the number out of it: https://dune.com/queries/1215383 and 1215383 both work.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).
- Query parameter values (`query_parameters`, object): Values for the query's parameters, as name/value pairs, for example blockchain: ethereum. Leave a parameter out and Dune uses the default set on the query. Skip this entirely for a query without parameters.

**Outputs**

- `execution_id` (text): Id of the run that was started
- `is_finished` (true/false): Whether it has already reached a final state
- `query_id` (number): The query that ran
- `query_url` (text): Its page on dune.com
- `state` (text): Dune's state constant
- `state_label` (text): That state in plain words

**Example output**

```json
{
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "is_finished": false,
  "query_id": 1215383,
  "query_url": "https://dune.com/queries/1215383",
  "state": "QUERY_STATE_PENDING",
  "state_label": "Queued"
}
```

### Start a SQL run

Start raw DuneSQL running and return straight away with its execution id, without waiting for the rows. The asynchronous half of Run SQL: use it for a statement too slow to hold a workflow open on, then collect the rows later with Get execution results.

**Inputs**

- SQL (`sql`, text, required): The DuneSQL to run. Same statement Run SQL takes; this one starts it and returns without waiting for the rows.
- Engine size (`performance`, text): How much compute to give the run. Credits are charged for what the run actually uses, so a bigger engine finishes sooner but costs more. Not every plan includes every engine, and Dune rejects one your subscription does not have, so leave this empty unless you know yours does. Empty runs the query on whichever engine it is set to use, which always works. One of: `medium` (Medium: Dune's default, and the one every plan has), `large` (Large: 2x compute for heavy joins, on paid plans), `small` (Small: cheapest, but not included in every plan).

**Outputs**

- `execution_id` (text): Id of the run that was started
- `is_finished` (true/false): Whether it has already reached a final state
- `query_id` (number): Always null; raw SQL is not a saved query
- `query_url` (text): Always null; there is no page for raw SQL
- `state` (text): Dune's state constant
- `state_label` (text): That state in plain words

**Example output**

```json
{
  "execution_id": "01HKZJ2683PHF9Q9PHHQ8FW4Q1",
  "is_finished": false,
  "query_id": null,
  "query_url": null,
  "state": "QUERY_STATE_PENDING",
  "state_label": "Queued"
}
```

### Upload a CSV

Turn a CSV into a Dune table in one step, with the columns and their types worked out from the file. The quickest way to get your own data next to onchain data (a list of wallets to label, a price series, a team's targets) and query the two together in SQL. Uploading to a name that already exists replaces what was there, so a scheduled workflow can keep the table current; use Create a table and Insert rows instead when the data has to build up.

**Inputs**

- Table name (`table_name`, text, required): What to call the table. Lower case, letters, numbers and underscores. Uploading to a name that already exists replaces its contents.
- CSV (`csv_data`, text, required): The CSV to upload, with the column names on the first line. Upload a file, or use the data a previous step produced.
- Description (`description`, text): What the table holds and where the data came from.
- Keep it private (`is_private`, true/false): Private tables are visible only to your account or team. Leave off to let anyone on Dune query it. Default: `false`.

**Outputs**

- `bytes` (number): Size of the CSV
- `column_names` (list): The header row, split up
- `full_name` (text): The name to write in SQL
- `name` (text): namespace.table_name: what the table fields take
- `row_count` (number): Rows uploaded, not counting the header
- `success` (true/false): Whether Dune accepted the upload
- `table_name` (text): Its name

**Example output**

```json
{
  "bytes": 48,
  "column_names": [
    "day",
    "dgs10"
  ],
  "full_name": "dune.my_team.interest_rates",
  "name": "my_team.interest_rates",
  "row_count": 2,
  "success": true,
  "table_name": "interest_rates"
}
```
