# Public API

### Where to find your organization's API keys

<figure><img src="/files/OhoUkiMEukm7xeKkMWJV" alt=""><figcaption></figcaption></figure>

### Authentication

All endpoints (except `/v1/health` and `/v1/auth/token`) require **Bearer JWT authentication.** One can obtain an short-lived access token using `/v1/auth/token` endpoint by exchanging `CLIENT_ID` and `CLIENT_SECRET` credentials. To obtain your client credentials (`CLIENT_ID` and `CLIENT_SECRET`), please the ConnectyAI Support team.

Token obtained from `/v1/auth/token` endpoint should be put in the `Authorization` header for all other requests:

```
-H "Authorization: Bearer <ACCESS_TOKEN>"
```

### API Address

The API URL depends on the organisation configuration regarding geolocation. Current list of addresses:

* `https://api.eu1.connecty-ai.com/` - for organisations registered in Europe.
* `https://api.us1.connecty-ai.com/` - for organisations registered in US.

### Endpoints

In the following endpoints `dw` stands for Data Workspace and `dw_id` represents and ID of given Data Workspace. Identifier of a Data Workspaces can be find on the ConnectyAI App in `Manager -> Data Environments -> {Selected DE} -> Data Workspaces -> Workspace ID`.

#### \[GET] /v1/health

This endpoint provides a health probe. It returns status code `200 OK`  if the ConnectyAI backend is operational.

#### Example

```
curl -X GET https://api.eu1.connecty-ai.com/v1/health
```

#### \[GET] /v1/auth/token

This endpoint exchanges your client API credentials for a short-lived access token.

#### Request body

* &#x20;  `client_id: string, required` - client identifier.
* `client_secret: string, required` - client secret.

```
{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET"
}
```

#### Response

```
{
    "access_token": "eyJhbGciOiJSUzI1N...",
    "expires_at": "2025-11-05T11:54:22.793708+01:00"
}
```

#### Example

```
curl -X POST https://api.eu1.connecty-ai.com/v1/auth/token \
  -H "content-type: application/json" \
  -d '{
        "client_id": "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET"
      }'
```

#### \[POST] /v1/dw/{dw\_id}/questions

This endpoint is an equivalent of asking a question in ConnectyAI chat for a given Data Workspace. It starts asynchronous question processing. It returns a handle for the new question immediately after the question processing starts. It does not wait for the question to be processed. To check the question processing state or to obtain the relevant question results, please use  `[GET]/v1/dw/{dwId}/questions/{questionId}/results` endpoint.

#### Request body

* &#x20;`question: string, required` - question, to be asked against Data Workspace with identifier equal to `dwId` .

```
{
    "question": "list the top 5 countries with the most orders"
}
```

#### Response

* `question_id: UUID` - identifier of asked question.

```
{
  "question_id": "729cb7a4-4b06-449e-a3c9-df40f5e570b8"
}
```

#### Example

```
curl -X POST https://api.eu1.connecty-ai.com/v1/dw/13/questions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $BEARER_TOKEN" \
  -d '{"question": "list the top 5 countries with the most orders"}'
```

#### \[GET] /v1/dw/{dw\_id}/questions/{question\_id}/results

This endpoint returns a state and results for previously aksed question. It supports partial result inclusion via the `include` query parameter and the result data frame size control with `max_rows` query parameter.

#### Path parameters

* `dw_id: int` - Data Workspace identifier.
* `question_id: UUID` - the identifier of asked question.

#### Query parameters

* `include: string, optional` - comma-separated string stating which result components includes in the response. Default values is `dataframe` and in this case only result data frame would be returned.
  * Possible values:
    * `dataframe`&#x20;
    * `statistics`&#x20;
    * `sqlquery`     &#x20;
    * `summary`
* `max_rows: int, optional, default=1000` - Maximum number of result rows, to return.

#### Response

In cases when given question is not yet completed, the response contains only the `state: string` field, for example:

```
{
    "state": "IN_PROGRESS"
}
```

Possbile state values:

* `PENDING`
* `IN_PROGRESS`
* `COMPLETED`
* `FAILED`

For successfully processed questions (`state: "COMPLETED"` ), the response is of the following structure.

* `state: string` - question processing state.
* `results: QuestionResults` - results corresponding to the given question.

Type `QuestionResults` is structured as follows:  &#x20;

```
{
    "response_summary": "string",
    "sql_query": "string",
    "dataframe": [][]object,
    "dataframe_stats": object
}
```

Additional comments about the `QuestionResults` structure:

* Field `dataframe` is a array of rows of data. It contains array of column names in the first array and the rest is rows of data.
* Filed `dataframe_stats` is an object representing a mapping from `column_name` , to that column statistics. Statistics calculated for a column depends on its type.

Example response

```
// run with include=dataframe,sqlquery,statistics and max_rows=3
{
  "state": "COMPLETED",
  "results": {
    "sql_query": "WITH ranked_logins AS (\n    SELECT \n        l.user_id, \n        l.login_at AS login_timestamp, \n        u.email AS user_email,\n        ROW_NUMBER() OVER (ORDER BY l.login_at DESC) AS login_rank\n    FROM \n        connectyailocal2.usr.logins l\n    JOIN \n        connectyailocal2.usr.users u ON l.user_id = u.user_id\n)\nSELECT \n    login_timestamp, \n    user_email\nFROM \n    ranked_logins\nWHERE \n    login_rank <= 100\nORDER BY \n    login_timestamp DESC;\n",
    "dataframe": [
      ["login_timestamp", "user_email"],
      ["2025-11-04T13:05:01.146+01:00", "damian@connectyai.com"],
      ["2025-11-04T11:48:15.46+01:00", "damian@connectyai.com"],
      ["2025-11-04T10:49:22.91+01:00", "damian@connectyai.com"]
    ],
    "dataframe_stats": {
      "login_timestamp": {
        "general": {
          "count": 100,
          "nulls_count": 0
        },
        "temporal": {
          "distinct_count": 100,
          "distinct_approx": false,
          "min": "2025-10-24T11:03:05.196568+02:00",
          "max": "2025-11-04T13:05:01.146482+01:00"
        }
      },
      "user_email": {
        "general": {
          "count": 100,
          "nulls_count": 0
        },
        "string": {
          "distinct_count": 2,
          "distinct_approx": false,
          "empty_string_count": 0,
          "min_len": 21,
          "mean_len": 22.44,
          "max_len": 45
        }
      }
    }
  }
}
```

#### Example

```
curl -X GET "https://api.eu1.connecty-ai.com/v1/dw/13/questions/729cb7a4-4b06-449e-a3c9-df40f5e570b8/results \
  -H "Authorization: Bearer $BEARER_TOKEN"

curl -X GET "https://api.eu1.connecty-ai.com/v1/dw/13/questions/729cb7a4-4b06-449e-a3c9-df40f5e570b8/results?include=dataframe,sqlquery,statistics&max_rows=50" \
  -H "Authorization: Bearer $BEARER_TOKEN"

```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://connectyai.gitbook.io/documentation/getting-started/public-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
