Setting up query API endpoints

[Edit this page](https://github.com/ClickHouse/clickhouse-docs/blob/main/docs/cloud/guides/SQL_console/query-endpoints.md)

The **Query API Endpoints** feature allows you to create an API endpoint directly from any saved SQL query in the ClickHouse Cloud console. You'll be able to access API endpoints via HTTP to execute your saved queries without needing to connect to your ClickHouse Cloud service via a native driver.

## Pre-requisites[​](#quick-start-guide "Direct link to Pre-requisites")

Before proceeding, ensure you have:

- An API key with appropriate permissions
- An Admin Console Role

You can follow this guide to [create an API key](/docs/cloud/manage/openapi) if you don't yet have one.

Minimum permissions

To query an API endpoint, the API key needs `Member` organization role with `Query Endpoints` service access. The database role is configured when you create the endpoint.

Create a saved query

### Create a saved query[​](#creating-a-saved-query "Direct link to Create a saved query")

If you have a saved query, you can skip this step.

Open a new query tab. For demonstration purposes, we'll use the [youtube dataset](/docs/getting-started/example-datasets/youtube-dislikes), which contains approximately 4.5 billion records.
Follow the steps in section ["Create table"](/docs/getting-started/example-datasets/youtube-dislikes#create-the-table) to create the table on your Cloud service and insert data to it.

Tip

`LIMIT` the number of rows

The example dataset tutorial inserts a lot of data - 4.65 billion rows which can take some time to insert.
For the purposes of this guide we recommend to use the `LIMIT` clause to insert a smaller amount of data,
for example 10 million rows.

As an example query, we'll return the top 10 uploaders by average views per video in a user-inputted `year` parameter.

```
WITH sum(view_count) AS view_sum,
  round(view_sum / num_uploads, 2) AS per_upload
SELECT
  uploader,
  count() AS num_uploads,
  formatReadableQuantity(view_sum) AS total_views,
  formatReadableQuantity(per_upload) AS views_per_video
FROM
  youtube
WHERE
-- highlight-next-line
  toYear(upload_date) = {year: UInt16}
GROUP BY uploader
ORDER BY per_upload desc
  LIMIT 10
```

Note that this query contains a parameter (`year`) which is highlighted in the snippet above.
You can specify query parameters using `{ }` together with the type of the parameter.
The SQL console query editor automatically detects ClickHouse query parameter expressions and provides an input for each parameter.

Let's quickly run this query to make sure that it works by specifying the year `2010` in the query variables input box on the right side of the SQL editor:

Next, save the query:

More documentation around saved queries can be found in section ["Saving a query"](/docs/cloud/get-started/sql-console#saving-a-query).

Configuring the query API endpoint

### Configuring the query API endpoint[​](#configuring-the-query-api-endpoint "Direct link to Configuring the query API endpoint")

Query API endpoints can be configured directly from query view by clicking the **Share** button and selecting `API Endpoint`.
You'll be prompted to specify which API keys should be able to access the endpoint:

After selecting an API key, you will be asked to:

- Select the Database role that will be used to run the query (`Full access`, `Read only` or `Create a custom role`)
- Specify cross-origin resource sharing (CORS) allowed domains

After selecting these options, the query API endpoint will automatically be provisioned.

An example `curl` command will be displayed so you can send a test request:

The curl command displayed in the interface is given below for convenience:

```
curl -H "Content-Type: application/json" -s --user '<key_id>:<key_secret>' '<API-endpoint>?format=JSONEachRow&param_year=<value>'
```

Query API parameters

### Query API parameters[​](#query-api-parameters "Direct link to Query API parameters")

Query parameters in a query can be specified with the syntax `{parameter_name: type}`. These parameters will be automatically detected and the example request payload will contain a `queryVariables` object through which you can pass these parameters.

Testing and monitoring

### Testing and monitoring[​](#testing-and-monitoring "Direct link to Testing and monitoring")

Once a Query API endpoint is created, you can test that it works by using `curl` or any other HTTP client:

After you've sent your first request, a new button should appear immediately to the right of the **Share** button. Clicking it will open a flyout containing monitoring data about the query:

## Implementation details[​](#implementation-details "Direct link to Implementation details")

This endpoint executes queries on your saved Query API endpoints.
It supports multiple versions, flexible response formats, parameterized queries, and optional streaming responses (version 2 only).

**Endpoint:**

```
GET /query-endpoints/{queryEndpointId}/run
POST /query-endpoints/{queryEndpointId}/run
```

### HTTP methods[​](#http-methods "Direct link to HTTP methods")

|  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Method Use Case Parameters|  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | | **GET** Simple queries with parameters Pass query variables via URL parameters (`?param_name=value`)| **POST** Complex queries or when using request body Pass query variables in request body (`queryVariables` object) | | | | | | | | |

**When to use GET:**

- Simple queries without complex nested data
- Parameters can be easily URL-encoded
- Caching benefits from HTTP GET semantics

**When to use POST:**

- Complex query variables (arrays, objects, large strings)
- When request body is preferred for security/privacy
- Streaming file uploads or large data

### Authentication[​](#authentication "Direct link to Authentication")

**Required:** Yes  
**Method:** Basic Auth using OpenAPI Key/Secret  
**Permissions:** Appropriate permissions for the query endpoint

### Request configuration[​](#request-configuration "Direct link to Request configuration")

#### URL parameters[​](#url-params "Direct link to URL parameters")

|  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- |
| Parameter Required Description|  |  |  | | --- | --- | --- | | `queryEndpointId` **Yes** The unique identifier of the query endpoint to run | | | | | |

#### Query parameters[​](#query-params "Direct link to Query parameters")

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Parameter Required Description Example|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | `format` No Response format (supports all ClickHouse formats) `?format=JSONEachRow`| `param_:name` No Query variables when request body is a stream. Replace `:name` with your variable name `?param_year=2024`| `request_timeout` No Query timeout in milliseconds (default: 30000) `?request_timeout=60000`| `:clickhouse_setting` No Any supported [ClickHouse setting](https://clickhouse.com/docs/operations/settings/settings) `?max_threads=8` | | | | | | | | | | | | | | | | | | | |

#### Headers[​](#headers "Direct link to Headers")

|  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Header Required Description Values|  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | | `x-clickhouse-endpoint-version` No Specifies the endpoint version `1` or `2` (defaults to last saved version)| `x-clickhouse-endpoint-upgrade` No Triggers endpoint version upgrade (use with version header) `1` to upgrade | | | | | | | | | | | |

---

### Request body[​](#request-body "Direct link to Request body")

#### Parameters[​](#params "Direct link to Parameters")