# Access EMQX Tables via HTTP API

EMQX Tables provides an HTTP API interface that allows users of Dedicated (legacy) and Serverless deployments to insert and query data directly through HTTP requests. This is useful for applications or scripts that prefer a simple HTTP integration rather than MQTT or SDK-based methods.

The HTTP API supports multiple protocols:

- **SQL**: Execute SQL statements for querying or inserting data.
- **PromQL**: Query data using Prometheus Query Language (PromQL).
- **InfluxDB Line Protocol**: Write data in the InfluxDB-compatible line format.

## SQL over HTTP

### Base URL

The HTTP API uses the Host address provided in the **Connection Info** section on the EMQX Tables Deployment Overview page.

It uses HTTPS protocol on port 443 (default, no need to specify).

Example:

```
https://k81a5888.ala.us-east-1.aws.emqxtables.com
```

All SQL-related requests are sent to the following endpoint:

```bash
<BASE_URL>/v1/sql
```

Example:

```bash
https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/sql
```

### Required Headers

Requests to the EMQX Tables HTTP API require specific headers to handle authentication and data format. All examples below use HTTPS protocol.

#### Authentication

EMQX Tables HTTP API uses Basic Authentication.

Add the following header to your request:

```sql
Authorization: Basic <Base64(username:password)>
```

- Both the **username** and **password** can be found on the EMQX Tables **Deployment Overview** page, under the **Connection Info** section in the EMQX Cloud console.
- These credentials are unique for each deployment and required for all API access.

To create the Base64-encoded string:

1. Concatenate your username and password with a colon:

   ```
   username:password
   ```

2. Encode the result with Base64.

For example:

```
Username: k81a5888q2aa1077
Password: p11cb3e282a77af1
```

After Base64 encoding:

```
azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx
```

Your header becomes:

```
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx
```

#### Other Headers

| Header                  | Description                                                  | Example                                           |
| ----------------------- | ------------------------------------------------------------ | ------------------------------------------------- |
| **Content-Type**        | The request body must be form-encoded.                       | `Content-Type: application/x-www-form-urlencoded` |
| **X-Greptime-Timeout**  | *(Optional)* Sets the server-side query timeout.             | `X-Greptime-Timeout: 120s`                        |
| **X-Greptime-Timezone** | *(Optional)* Sets the time zone for time-related SQL operations. | `X-Greptime-Timezone: +1:00`                      |

### Query Parameters

You can include optional query string parameters to control output format and database context.

| Parameter | Description                         | Default         | Notes                                                        |
| --------- | ----------------------------------- | --------------- | ------------------------------------------------------------ |
| `db`      | Specifies the target database name. | `public`        | Optional                                                     |
| `format`  | Specifies the output format.        | `greptimedb_v1` | Optional. Controls response format. See below for all supported formats. |

**Supported formats:**

- `greptimedb_v1`: Default JSON output.
- `influxdb_v1`: InfluxDB-compatible query response.
  - Additional parameter: `epoch` (`[ns, u, µ, ms, s, m, h]`) sets timestamp precision.
- `csv`: Outputs as comma-separated values without headers.
- `csvWithNames`: Outputs as comma-separated values with a column names header.
- `csvWithNamesAndTypes`: Outputs as comma-separated values with column names and data types headers.
- `arrow`: Apache Arrow IPC format
  - Additional parameter: `compression` (`zstd` or `lz4`), default: no compression.
- `table`: ASCII table output for console output.
- `null`: Concise text-only output of the row count and elapsed time, useful for evaluating query performance.

### Execute SQL Statements

Use the `POST` method with `application/x-www-form-urlencoded` content type. This content type means the request body is encoded as simple key-value pairs:

- **Key**: sql
- **Value**: The SQL statement to execute

Example request body:

```sql
sql=SHOW TABLES
```

### SQL Statements Examples

#### Example 1: List all tables

This example shows how to execute `SHOW TABLES` statement to list all the tables in `public` database.

**Request**

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/sql
Content-Type: application/x-www-form-urlencoded
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx

sql=SHOW TABLES
```

**Response**

```json
{
  "output": [
    {
      "records": {
        "schema": {
          "column_schemas": [
            { "name": "Tables", "data_type": "String" }
          ]
        },
        "rows": [
          ["sensor_temperature_humidity"]
        ],
        "total_rows": 1
      }
    }
  ],
  "execution_time_ms": 4
}
```

#### Example 2: Insert a record

This example inserts a new data row into the `sensor_temperature_humidity` table using an `INSERT INTO` SQL statement.

**Request**

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/sql
Content-Type: application/x-www-form-urlencoded
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx

sql=INSERT INTO sensor_temperature_humidity(device_id, temperature, humidity, ts) VALUES ('sensors001', 42.0, 42.0, now())
```

**Response**

```json
{
  "output": [
    { "affectedrows": 1 }
  ],
  "execution_time_ms": 2
}
```

#### Example 3: Query data (default JSON output)

This example queries all data from the `sensor_temperature_humidity` table and return the result in the default JSON format.

**Request**

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/sql
Content-Type: application/x-www-form-urlencoded
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx

sql=SELECT * FROM sensor_temperature_humidity
```

**Response**

```json
{
  "output": [
    {
      "records": {
        "schema": {
          "column_schemas": [
            { "name": "device_id", "data_type": "String" },
            { "name": "temperature", "data_type": "Float64" },
            { "name": "humidity", "data_type": "Float64" },
            { "name": "ts", "data_type": "TimestampMillisecond" }
          ]
        },
        "rows": [
          ["sensors001", 42.0, 42.0, 1764150607785]
        ],
        "total_rows": 1,
        "metrics": { "greptime_cloud_rcu": 1 }
      }
    }
  ],
  "execution_time_ms": 3
}
```

#### Example 4: Query data (CSV output)

This example queries all data from the `sensor_temperature_humidity` table and return the result in CSV format.

**Request**

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/sql?format=csv
Content-Type: application/x-www-form-urlencoded
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx

sql=SELECT * FROM sensor_temperature_humidity
```

**Response**

```json
sensors001,42.0,42.0,1764150607785
```

### Notes

- **Default database:** All SQL queries operate on the `public` database unless `db` is specified in the query string.
- **Timeouts:** Long-running queries can be terminated early by setting `X-Greptime-Timeout`.
- **Time zone:** Use `X-Greptime-Timezone` to control how timestamps are interpreted and returned.
- **Security:** Always use HTTPS and never share your plain credentials.
- **Response time:** The `execution_time_ms` field indicates server-side query duration.

## PromQL over HTTP

EMQX Tables supports querying time-series data using Prometheus Query Language (PromQL) through HTTP APIs.

Two types of PromQL-compatible APIs are available:

1. **Prometheus-compatible APIs**: Returns results in standard Prometheus response format.
2. **GreptimeDB JSON output API**: Returns results in GreptimeDB’s data-frame format, similar to SQL queries.

Both options support HTTPS and Basic Authentication.

### Prometheus-Compatible PromQL APIs

#### Endpoints

EMQX Tables exposes Prometheus-compatible query APIs under `/v1/prometheus/api/v1`:

| Operation     | Endpoint                                          |
| ------------- | ------------------------------------------------- |
| Instant query | `/v1/prometheus/api/v1/query`                     |
| Range query   | `/v1/prometheus/api/v1/query_range`               |
| Series        | `/v1/prometheus/api/v1/series`                    |
| Label names   | `/v1/prometheus/api/v1/labels`                    |
| Label values  | `/v1/prometheus/api/v1/label/<label_name>/values` |

All endpoints support both **GET** and **POST**.

#### Required Headers

| Header            | Description                                                  |
| ----------------- | ------------------------------------------------------------ |
| **Authorization** | Same as SQL API: `Authorization: Basic <Base64(username:password)>` |
| **Content-Type**  | Required only for POST requests: `application/x-www-form-urlencoded` |

#### Query Parameters

| Parameter | Description   | Default  |
| --------- | ------------- | -------- |
| `db`      | Database name | `public` |

Additional query parameters follow the Prometheus specification:

- For **GET** requests: Pass query parameters as URL encoded strings. Refer to [Prometheus documentation](https://prometheus.io/docs/prometheus/latest/querying/api/).
- For **POST** requests: Provide parameters using `application/x-www-form-urlencoded` body.

#### Request Body (POST)

For POST requests, include the PromQL parameters using form-encoded key-value pairs.

Example keys:

- `query`
- `start`
- `end`
- `step`

#### Example: Range Query (60-second step)

Query temperature values during a 10-minute period.

##### Request

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/prometheus/api/v1/query_range
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx
Content-Type: application/x-www-form-urlencoded

query=sensor_temperature
start=2025-11-28T10:00:00Z
end=2025-11-28T10:10:00Z
step=60s
```

##### Response (200 OK)

```json
{
    "status": "success",
    "data": {
        "resultType": "matrix",
        "result": [
            {
                "metric": {
                    "__name__": "sensor_temperature",
                    "device_id": "sensor_1"
                },
                "values": [
                    [
                        1764324000.0,
                        "22.5"
                    ],
                    [
                        1764324060.0,
                        "22.600000381469727"
                    ],
                    [
                        1764324120.0,
                        "22.700000762939453"
                    ],
                    [
                        1764324180.0,
                        "22.799999237060547"
                    ],
                    [
                        1764324240.0,
                        "22.899999618530273"
                    ],
                    [
                        1764324300.0,
                        "23"
                    ],
                    [
                        1764324360.0,
                        "23.100000381469727"
                    ],
                    [
                        1764324420.0,
                        "23.200000762939453"
                    ],
                    [
                        1764324480.0,
                        "23.299999237060547"
                    ],
                    [
                        1764324540.0,
                        "23.399999618530273"
                    ],
                    [
                        1764324600.0,
                        "23.399999618530273"
                    ]
                ]
            }
        ]
    }
}   
```

#### Example: Range Query with `irate()` (3-minute window)

Query the temperature increase rate over a time range, using a 3-minute calculation window and a 60-second step.

##### Request

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/prometheus/api/v1/query_range
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx
Content-Type: application/x-www-form-urlencoded

query=irate(sensor_temperature[3m])
start=2025-11-28T10:00:00Z
end=2025-11-28T10:10:00Z
step=60s
```

##### Response (200 OK)

```json
{
    "status": "success",
    "data": {
        "resultType": "matrix",
        "result": [
            {
                "metric": {
                    "__name__": "sensor_temperature",
                    "device_id": "sensor_1"
                },
                "values": [
                    [
                        1764324060.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324120.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324180.0,
                        "0.0016666412353515624"
                    ],
                    [
                        1764324240.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324300.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324360.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324420.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324480.0,
                        "0.0016666412353515624"
                    ],
                    [
                        1764324540.0,
                        "0.0016666730244954428"
                    ],
                    [
                        1764324600.0,
                        "0.0016666730244954428"
                    ]
                ]
            }
        ]
    }
}
```

### GreptimeDB JSON Format PromQL API

EMQX Tables also exposes an API that executes PromQL but returns results using the same data-frame JSON format as the SQL API.

#### Endpoint

```
GET /v1/promql
```

#### Required Headers

| Header            | Description                                                  |
| ----------------- | ------------------------------------------------------------ |
| **Authorization** | Same as SQL API: `Authorization: Basic <Base64(username:password)>` |

#### Query Parameters

| Parameter | Description                                                |
| --------- | ---------------------------------------------------------- |
| `db`      | Database name (default = `public`)                         |
| `query`   | PromQL expression                                          |
| `start`   | Start time (`rfc3339` or `unix_timestamp`)                 |
| `end`     | End time (`rfc3339` or `unix_timestamp`)                   |
| `step`    | Resolution step, supports duration format or float seconds |
| `format`  | Optional output format (same as SQL API formats)           |

#### Supported Timestamp Formats

Examples of valid `start`/`end` values:

**RFC3339**

- `2015-07-01T20:11:00Z` (default to seconds resolution)
- `2015-07-01T20:11:00.781Z` (with milliseconds resolution)
- `2015-07-02T04:11:00+08:00` (with timezone offset)

**Unix timestamp**

- `1435781460` (default to seconds resolution)
- `1435781460.781` (with milliseconds resolution)

**Duration formats**

- `1h` (1 hour)
- `5d1m` (5 days and 1 minute)
- `2` (2 seconds)
- `2s` (also 2 seconds)

#### Example: `irate()` Query (GreptimeDB JSON Format)

Query the temperature increase rate over a time range, using a 3-minute calculation window and a 60-second step.

##### Request

```
GET https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/promql?query=irate(sensor_temperature[3m])&start=2025-11-28T10:00:00Z&end=2025-11-28T10:10:00Z&step=60s
Authorization: Basic azgxYTU4ODhxMmFhMTA3NzpwMTFjYjNlMjgyYTc3YWYx
```

##### Response (200 OK)

```json
{
    "output": [
        {
            "records": {
                "schema": {
                    "column_schemas": [
                        {
                            "name": "ts",
                            "data_type": "TimestampMillisecond"
                        },
                        {
                            "name": "prom_irate(ts_range,temperature)",
                            "data_type": "Float64"
                        },
                        {
                            "name": "device_id",
                            "data_type": "String"
                        }
                    ]
                },
                "rows": [
                    [
                        1764324060000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324120000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324180000,
                        0.0016666412353515624,
                        "sensor_1"
                    ],
                    [
                        1764324240000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324300000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324360000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324420000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324480000,
                        0.0016666412353515624,
                        "sensor_1"
                    ],
                    [
                        1764324540000,
                        0.0016666730244954428,
                        "sensor_1"
                    ],
                    [
                        1764324600000,
                        0.0016666730244954428,
                        "sensor_1"
                    ]
                ],
                "total_rows": 10,
                "metrics": {
                    "greptime_cloud_rcu": 2
                }
            }
        }
    ],
    "execution_time_ms": 5
}
```

## InfluxDB Line Protocol over HTTP

EMQX Tables supports ingesting time-series data using the InfluxDB Line Protocol, compatible with InfluxDB write APIs.

### Endpoint

```
POST /v1/influxdb/api/v2/write
```

### Query Parameters

| Parameter   | Description                                 | Default  |
| ----------- | ------------------------------------------- | -------- |
| `db`        | Target database                             | `public` |
| `precision` | Timestamp precision (`ns`, `us`, `ms`, `s`) | `ns`     |

### Required Headers

#### Authorization

Unlike the SQL and PromQL APIs, the InfluxDB Line Protocol API uses a different authentication format:

```sql
Authorization: token <username:password>
```

For example, if the username is `k81a5888q2aa1077` and the password is `p11cb3e282a77af1`, the header becomes:

```
Authorization: token k81a5888q2aa1077:p11cb3e282a77af1
```

### Request Body

Send a raw string formatted according to the InfluxDB Line Protocol specification.

Example:

```
sensor_temperature_humidity,device_id="sensor001" temperature=42.0,humidity=42.0 1764295258644
```

### Response

| Status             | Meaning          |
| ------------------ | ---------------- |
| **204 No Content** | Write successful |

No response body is returned.

### Example

This example writes a single data point using InfluxDB Line Protocol.

#### Request

```
POST https://k81a5888.ala.us-east-1.aws.emqxtables.com/v1/influxdb/api/v2/write?precision=ms
Authorization: token k81a5888q2aa1077:p11cb3e282a77af1

sensor_temperature_humidity,device_id="sensor001" temperature=42.0,humidity=42.0 1764295258644
```

#### Response

```
204 No Content
```