> ## Documentation Index
> Fetch the complete documentation index at: https://honeydew.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# GraphQL API

Honeydew provides a GraphQL API, that allows to directly call the Honeydew service.

<Note>
  This guide covers a direct connection to the Honeydew API using GraphQL.

  It is also possible to use Honeydew APIs with a
  [Snowflake Connection](https://docs.snowflake.com/en/developer-guide/python-connector/python-connector),
  by calling the [Snowflake Native Application](/docs/integration/snowflake-native-app) API.
</Note>

<Warning>
  Public GraphQL API is not enabled by default. To enable for your organization, please contact [support@honeydew.ai](mailto:support@honeydew.ai).
</Warning>

## Use Cases

### Embedded Analytics

The GraphQL API can be used to build embedded analytics applications that leverage the semantic layer.
This allows you to build custom applications that use the semantic layer to generate queries and retrieve data.

### Building custom AI analyst applications

The GraphQL API can be used to build custom AI analyst applications that leverage the semantic layer
to answer user questions in natural language.

### Metadata Sharing

The GraphQL API can be used to share metadata with other applications or services.
For example, you can use the GraphQL API to share metadata with a data catalog or a data governance tool,
or to import metadata from another system into Honeydew.

### BI Integration

The GraphQL API can be used to publish metadata to BI tools, such as Tableau, Power BI, Thoughtspot, and more.

### Development and Testing

The GraphQL API can be used to develop and test semantic layer definitions.
Developers can use their favorite development tools to edit the semantic layer definitions, push them directly to git,
and use the GraphQL APIs to validate the definitions.
These validations can also be integrated into CI/CD pipelines to ensure that the semantic layer definitions
are valid before deploying them to production.

## Usage

### Security

You can use the GraphQL API with an [API Key and Secret](/docs/initial-setup#api-keys).
You cannot use the GraphQL API with a Honeydew username and password.

<Note>
  Different API queries and mutations require different permissions. Therefore, in order to follow
  the principal of least privileges as a best practice, you may need to create different API keys for different use cases.

  Each query or mutation below specifies the required permissions.
</Note>

<Tip>
  It is recommended to restrict API access to specific IP addresses or ranges,
  by using the [IP Access Control](/docs/access-control/ip-access-control) feature.
  To set up IP Access Control, please contact [support@honeydew.ai](mailto:support@honeydew.ai).
</Tip>

### API Endpoint

The default API endpoint is `https://api.honeydew.cloud/api/public/v1/graphql`.
If your organization uses a custom hostname for the API connection,
you can locate it in the Honeydew UI, under the **API** section in **Settings**.

### Headers

The following custom Honeydew headers can be used in the API requests:

* `X-Honeydew-Client`: A string that identifies the client making the request.
  Use it to identify the client in Honeydew logs and query history, for audit, debugging and support purposes.
* `X-Honeydew-Workspace`: The name of the workspace to use for the request.
  This is required for most queries and mutations that operate on a specific workspace.
* `X-Honeydew-Branch`: The name of the branch to use for the request.
  This is required for most queries and mutations that operate on a specific branch.

### Rate Limiting

The Public API implements rate limiting to ensure fair usage and system stability. Rate limits are applied per user (or per API key) and are enforced according to industry standards.

**Default Rate Limit**: 60 calls per user/key per minute

**Response Headers**: The API provides rate limit information through standard HTTP response headers:

* `RateLimit-Limit`: The maximum number of requests allowed per time window
* `RateLimit-Remaining`: The number of requests remaining in the current time window
* `RateLimit-Reset`: The timestamp when the rate limit will reset (in Unix epoch seconds)

<Tip>
  Monitor these headers in your API responses to implement proper rate limiting in your applications and avoid hitting rate limits unexpectedly.
</Tip>

<Warning>
  When you exceed the rate limit, the API will return a `429 Too Many Requests` HTTP status code. Implement exponential backoff and retry logic in your applications to handle rate limiting gracefully.
</Warning>

<Note>
  If you need to increase your rate limits beyond the default, please contact [support@honeydew.ai](mailto:support@honeydew.ai) to discuss your requirements.
</Note>

### API integration example

Below we have provided API integration examples for Python, JavaScript and cURL.
The API can be used with any programming language that supports HTTP requests.

<Tip>
  To learn more about GraphQL, you can refer to the [GraphQL documentation](https://graphql.org/learn/)
</Tip>

<Tabs>
  <Tab title="Python">
    <Note>
      This example uses the `requests` library to make HTTP requests to the Honeydew API.
      To install it, run:

      ```bash theme={null}
      pip install requests
      ```
    </Note>

    ```python theme={null}
    import requests
    from requests.auth import HTTPBasicAuth

    # Replace with your Honeydew API Key and Secret
    API_KEY = "your_api_key_here"
    API_SECRET = "your_api_secret_here"


    # Honeydew API endpoint
    # If your organization uses a custom hostname, use it here instead of the default
    HONEYDEW_API_HOSTNAME = "api.honeydew.cloud"
    API_URI = f"https://{HONEYDEW_API_HOSTNAME}/api/public/v1/graphql"


    # Example of a GraphQL query to get workspaces
    # Since the graphql call is at a global level, we don't need to specify workspace or branch here

    WORKSPACES_QUERY = """
        query {
            workspaces {
                name
            }
        }
    """

    response = requests.post(
        API_URI,
        json={"query": WORKSPACES_QUERY},
        auth=HTTPBasicAuth(API_KEY, API_SECRET),
        timeout=30,
        headers={
            "Content-Type": "application/json",
            "X-Honeydew-Client": "python-script",
        },
    )
    response.raise_for_status()  # Raise an error for bad responses

    print("Response from Honeydew API:", response.json())


    # Example of a GraphQL query to get entities of a specific workspace

    WORKSPACE_NAME = "tpch"
    BRANCH_NAME = "prod"

    ENTITIES_QUERY = """
        query {
            entities {
                name
            }
        }
    """

    response = requests.post(
        API_URI,
        json={"query": ENTITIES_QUERY},
        auth=HTTPBasicAuth(API_KEY, API_SECRET),
        timeout=30,
        headers={
            "Content-Type": "application/json",
            "X-Honeydew-Client": "python-script",
            "X-Honeydew-Workspace": WORKSPACE_NAME,
            "X-Honeydew-Branch": BRANCH_NAME,
        },
    )
    response.raise_for_status()  # Raise an error for bad responses

    print("Response from Honeydew API:", response.json())


    # Example of a GraphQL query to get a specific entity with variables
    ENTITY_QUERY = """
        query getEntity($name: String!) {
            entity(name: $name) {
                name
                keys
            }
        }
    """

    response = requests.post(
        API_URI,
        json={
            "query": ENTITY_QUERY,
            "variables": {"name": "customers"},
        },
        auth=HTTPBasicAuth(API_KEY, API_SECRET),
        timeout=30,
        headers={
            "Content-Type": "application/json",
            "X-Honeydew-Client": "python-script",
            "X-Honeydew-Workspace": WORKSPACE_NAME,
            "X-Honeydew-Branch": BRANCH_NAME,
        },
    )
    response.raise_for_status()  # Raise an error for bad responses

    print("Response from Honeydew API:", response.json())

    # Example of a GraphQL mutation to reload workspace
    RELOAD_ALL_WORKSPACES = """
        mutation ReloadAllWorkspaces {
            reset_all_workspaces
        }
    """

    response = requests.post(
        API_URI,
        json={
            "query": RELOAD_ALL_WORKSPACES,
        },
        auth=HTTPBasicAuth(API_KEY, API_SECRET),
        timeout=30,
        headers={
            "Content-Type": "application/json",
        },
    )
    response.raise_for_status()  # Raise an error for bad responses

    print("Response from Honeydew API:", response.json())
    ```

    The above will produce the following kind of output:

    ```
    Response from Honeydew API: {'data': {'workspaces': [{'name': 'tasty_bytes'}, {'name': 'tpch'}]}}
    Response from Honeydew API: {'data': {'entities': [{'name': 'customers'}, {'name': 'order_lines'}, {'name': 'orders'}, {'name': 'parts'}, {'name': 'sessions'}]}}
    Response from Honeydew API: {'data': {'entity': {'keys': ['custkey'], 'name': 'customers'}}}
    Response from Honeydew API: {'data': {'reset_all_workspaces': None}}
    ```

    <Note>
      The above examples are basic and do not include error handling.
      In production code, you should handle errors and exceptions appropriately.
      We recommended using a graphql client library for more complex queries and mutations.
    </Note>
  </Tab>

  <Tab title="JavaScript">
    <Note>
      This example uses the `axios` package to make HTTP requests to the Honeydew API.
      To install it, run:

      ```bash theme={null}
      npm install axios
      ```
    </Note>

    ```JavaScript theme={null}
    const axios = require('axios');

    // Replace with your Honeydew API Key and Secret
    const API_KEY = "your_api_key_here";
    const API_SECRET = "your_api_secret_here";

    // Honeydew API endpoint
    // If your organization uses a custom hostname, use it here instead of the default
    const HONEYDEW_API_HOSTNAME = "api.honeydew.cloud";
    const API_URI = `https://${HONEYDEW_API_HOSTNAME}/api/public/v1/graphql`;

    // Example of a GraphQL query to get workspaces
    // Since the graphql call is at a global level, we don't need to specify workspace or branch here
    const WORKSPACES_QUERY = `
        query {
            workspaces {
                name
            }
        }
    `;

    axios
      .post(
        API_URI,
        { query: WORKSPACES_QUERY },
        {
          auth: {
            username: API_KEY,
            password: API_SECRET,
          },
          timeout: 30000,
          headers: {
            "Content-Type": "application/json",
            "X-Honeydew-Client": "javascript-app",
          },
        }
      )
      .then((response) => {
        console.log(
          "Response from Honeydew API: " + JSON.stringify(response.data, null, 2)
        );
      });

    // Example of a GraphQL query to get entities of a specific workspace
    const WORKSPACE_NAME = "tpch";
    const BRANCH_NAME = "prod";

    const ENTITIES_QUERY = `
        query {
            entities {
                name
            }
        }
    `;

    axios
      .post(
        API_URI,
        { query: ENTITIES_QUERY },
        {
          auth: {
            username: API_KEY,
            password: API_SECRET,
          },
          timeout: 30000,
          headers: {
            "Content-Type": "application/json",
            "X-Honeydew-Client": "javascript-app",
            "X-Honeydew-Workspace": WORKSPACE_NAME,
            "X-Honeydew-Branch": BRANCH_NAME,
          },
        }
      )
      .then((response) => {
        console.log(
          "Response from Honeydew API: " + JSON.stringify(response.data, null, 2)
        );
      });

    // Example of a GraphQL query to get a specific entity with variables
    const ENTITY_QUERY = `
        query getEntity($name: String!) {
            entity(name: $name) {
                name
                keys
            }
        }
    `;

    axios
      .post(
        API_URI,
        {
          query: ENTITY_QUERY,
          variables: { name: "customers" },
        },
        {
          auth: {
            username: API_KEY,
            password: API_SECRET,
          },
          timeout: 30000,
          headers: {
            "Content-Type": "application/json",
            "X-Honeydew-Client": "javascript-app",
            "X-Honeydew-Workspace": WORKSPACE_NAME,
            "X-Honeydew-Branch": BRANCH_NAME,
          },
        }
      )
      .then((response) => {
        console.log(
          "Response from Honeydew API: " + JSON.stringify(response.data, null, 2)
        );
      });

    // Example of a GraphQL mutation to reload workspace
    const RELOAD_ALL_WORKSPACES = `
        mutation ReloadAllWorkspaces {
            reset_all_workspaces
        }
    `;

    axios
      .post(
        API_URI,
        { query: RELOAD_ALL_WORKSPACES },
        {
          auth: {
            username: API_KEY,
            password: API_SECRET,
          },
          timeout: 30000,
          headers: {
            "Content-Type": "application/json",
            "X-Honeydew-Client": "javascript-app",
          },
        }
      )
      .then((response) => {
        console.log(
          "Response from Honeydew API: " + JSON.stringify(response.data, null, 2)
        );
      });
    ```

    The above will produce the following kind of output:

    ```
    Response from Honeydew API: {
      "data": {
        "workspaces": [
          {
            "name": "tasty_bytes"
          },
          {
            "name": "tpch"
          }
        ]
      }
    }
    Response from Honeydew API: {
      "data": {
        "entities": [
          {
            "name": "customers"
          },
          {
            "name": "order_lines"
          },
          {
            "name": "orders"
          },
          {
            "name": "parts"
          },
          {
            "name": "sessions"
          }
        ]
      }
    }
    Response from Honeydew API: {
      "data": {
        "entity": {
          "keys": [
            "custkey"
          ],
          "name": "customers"
        }
      }
    }
    Response from Honeydew API: {
      "data": {
        "reset_all_workspaces": null
      }
    }
    ```

    <Note>
      The above examples are basic and do not include error handling.
      In production code, you should handle errors and exceptions appropriately.
      We recommended using a graphql client library for more complex queries and mutations.
    </Note>
  </Tab>

  <Tab title="cURL">
    <Note>
      This example uses `curl` to make HTTP requests to the Honeydew API.
      `curl` is typically pre-installed on most systems.
    </Note>

    ```bash theme={null}
    # Replace with your Honeydew API Key and Secret
    export API_KEY="your_api_key_here"
    export API_SECRET="your_api_secret_here"

    # Honeydew API endpoint
    # If your organization uses a custom hostname, use it here instead of the default
    export HONEYDEW_API_HOSTNAME="api.honeydew.cloud"
    export API_URI="https://${HONEYDEW_API_HOSTNAME}/api/public/v1/graphql"

    echo "=== Example 1: Querying workspaces ==="
    # Example of a GraphQL query to get workspaces
    # Since the graphql call is at a global level, we don't need to specify workspace or branch here
    export WORKSPACES_QUERY='{
      "query": "query { workspaces { name } }"
    }'

    curl -X POST "${API_URI}" \
      -H "Content-Type: application/json" \
      -H "X-Honeydew-Client: curl-script" \
      -u "${API_KEY}:${API_SECRET}" \
      -d "${WORKSPACES_QUERY}" \
      --max-time 30


    echo -e "\n\n=== Example 2: Querying entities of a specific workspace ==="
    # Example of a GraphQL query to get entities of a specific workspace
    export WORKSPACE_NAME="tpch"
    export BRANCH_NAME="prod"
    export ENTITIES_QUERY='{
      "query": "query { entities { name } }"
    }'

    curl -X POST "${API_URI}" \
      -H "Content-Type: application/json" \
      -H "X-Honeydew-Client: curl-script" \
      -H "X-Honeydew-Workspace: ${WORKSPACE_NAME}" \
      -H "X-Honeydew-Branch: ${BRANCH_NAME}" \
      -u "${API_KEY}:${API_SECRET}" \
      -d "${ENTITIES_QUERY}" \
      --max-time 30


    echo -e "\n\n=== Example 3: Querying a specific entity with variables ==="
    # Example of a GraphQL query to get a specific entity with variables
    export ENTITY_QUERY='{
      "query": "query getEntity($name: String!) { entity(name: $name) { name keys } }",
      "variables": { "name": "customers" }
    }'

    curl -X POST "${API_URI}" \
      -H "Content-Type: application/json" \
      -H "X-Honeydew-Client: curl-script" \
      -H "X-Honeydew-Workspace: ${WORKSPACE_NAME}" \
      -H "X-Honeydew-Branch: ${BRANCH_NAME}" \
      -u "${API_KEY}:${API_SECRET}" \
      -d "${ENTITY_QUERY}" \
      --max-time 30


    echo -e "\n\n=== Example 4: Using a mutation to reload all workspaces ==="
    # Example of a GraphQL mutation to reload workspace
    export RELOAD_ALL_WORKSPACES='{
      "query": "mutation ReloadAllWorkspaces { reset_all_workspaces }"
    }'

    curl -X POST "${API_URI}" \
      -H "Content-Type: application/json" \
      -H "X-Honeydew-Client: curl-script" \
      -u "${API_KEY}:${API_SECRET}" \
      -d "${RELOAD_ALL_WORKSPACES}" \
      --max-time 30

    echo -e "\n"
    ```

    The above will produce the following kind of output:

    ```
    === Example 1: Querying workspaces ===
    {
      "data": {
        "workspaces": [
          {
            "name": "tasty_bytes"
          },
          {
            "name": "tpch"
          }
        ]
      }
    }


    === Example 2: Querying entities of a specific workspace ===
    {
      "data": {
        "entities": [
          {
            "name": "customers"
          },
          {
            "name": "order_lines"
          },
          {
            "name": "orders"
          },
          {
            "name": "parts"
          },
        ]
      }
    }


    === Example 3: Querying a specific entity with variables ===
    {
      "data": {
        "entity": {
          "keys": [
            "custkey"
          ],
          "name": "customers"
        }
      }
    }


    === Example 4: Using a mutation to reload all workspaces ===
    {
      "data": {
        "reset_all_workspaces": null
      }
    }
    ```
  </Tab>
</Tabs>

## GraphQL API Reference

### Workspaces and Branches

<AccordionGroup>
  <Accordion title="List Workspaces">
    **Workspace/Branch Headers:** Not required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Query theme={null}
    query {
      workspaces {
        branch
        dwh_connector_name
        errors {
          description
        }
        git_url
        name
        object_key
      }
    }
    ```
  </Accordion>

  <Accordion title="Create Workspace Branch">
    This mutation creates a new branch in the specified workspace.

    **Workspace/Branch Headers:** Not required

    **Permissions:** Editor or higher

    ```graphql GraphQL Mutation theme={null}
    mutation createWorkspaceBranch($workspace_name: String!, $branch_name: String!) {
        create_workspace_branch(
            workspace_name: $workspace_name
            branch_name: $branch_name
        )
    }
    ```

    ```json Successful Result Example theme={null}
    {
      "data": {
        "create_workspace_branch": null
      }
    }
    ```

    ```json Error Example theme={null}
    {
      "data": {
        "create_workspace_branch": null
      },
      "errors": [
        {
          "locations": [
            {
              "column": 3,
              "line": 2
            }
          ],
          "message": "Workspace \"tpchaa\" is not found",
          "path": [
            "create_workspace_branch"
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Sync Table from Source">
    This mutation syncs a specific entity's table from its source, refreshing the metadata in the semantic layer.

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `dataset_object_key`: The object key of the dataset
      to sync. You can find dataset object keys by querying
      the entity's fields and looking for the `DataSet`
      type's `object_key` field.

    ```graphql GraphQL Mutation theme={null}
    mutation syncTableFromSource(
        $dataset_object_key: String!
    ) {
        sync_table_from_source(
            dataset_object_key: $dataset_object_key
        )
    }
    ```
  </Accordion>

  <Accordion title="Sync All Tables from Source">
    This mutation syncs all tables from their sources, refreshing the metadata in the semantic layer.

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    ```graphql GraphQL Mutation theme={null}
    mutation syncAllTablesFromSource {
        sync_all_tables_from_source
    }
    ```
  </Accordion>

  <Accordion title="Reload Workspace">
    This mutation reloads the specified workspace from Git.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Mutation theme={null}
    mutation reloadWorkspace {
        reset_workspace
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "reset_workspace": null
      }
    }
    ```
  </Accordion>

  <Accordion title="Reload All Workspaces">
    This mutation reloads all workspaces from Git.

    **Workspace/Branch Headers:** Not required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Mutation theme={null}
    mutation reloadAllWorkspaces {
        reset_all_workspaces
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "reset_all_workspaces": null
      }
    }
    ```
  </Accordion>

  <Accordion title="Reload Workspace for All Users">
    This mutation reloads a workspace from Git for all users.
    This is useful for ensuring that all users see
    the latest changes in the workspace.

    **Workspace/Branch Headers:** Required

    **Permissions:** Admin

    ```graphql GraphQL Mutation theme={null}
    mutation reloadWorkspaceAllUsers {
        reset_workspace_all_users
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "reset_workspace_all_users": null
      }
    }
    ```
  </Accordion>

  <Accordion title="Reload All Workspaces for All Users">
    This mutation reloads all workspaces from Git
    for all users.
    This is useful for ensuring that all users see
    the latest changes in all workspaces,
    in particular after a workspace was added or deleted.

    **Workspace/Branch Headers:** Not required

    **Permissions:** Admin

    ```graphql GraphQL Mutation theme={null}
    mutation reloadAllWorkspacesAllUsers {
        reset_all_workspaces_all_users
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "reset_all_workspaces_all_users": null
      }
    }
    ```
  </Accordion>
</AccordionGroup>

### Querying Schema

<AccordionGroup>
  <Accordion title="List Entities">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Query theme={null}
    query {
        entities {
            ai_description
            description
            display_name
            error {
                description
            }
            fields {
                description
                display_name
                error {
                    description
                }
                folder
                generated_display_name
                generated_folder_name
                git_url
                hidden
                labels
                metadata {
                    metadata {
                        name
                        value
                    }
                    name
                }
                name
                object_key
                owner
                tags {
                    key
                    value
                    source
                }
                ui_url
                ... on CalcAttribute {
                    owner
                    datatype
                    sql
                    timegrain
                }
                ... on DataSet {
                    dataset_type
                    owner
                    sql
                }
                ... on DataSetAttribute {
                    column
                    dataset
                    datatype
                    timegrain
                }
                ... on Metric {
                    datatype
                    owner
                    rollup
                    sql
                }
            }
            generated_display_name
            git_url
            hidden
            is_time_spine
            keys
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            relations {
                connection {
                    src_field
                    target_field
                }
                connection_expr {
                    sql
                }
                cross_filtering
                rel_join_type
                rel_type
                target_entity
            }
            tags {
                key
                value
                source
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Get Entity By Name">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `entity_name`: The name of the entity to retrieve

    ```graphql GraphQL Query theme={null}
    query getEntityByName($entity_name: String!) {
        entity(name: $entity_name) {
            ai_description
            description
            display_name
            error {
                description
            }
            generated_display_name
            git_url
            hidden
            is_time_spine
            keys
            labels
            metadata {
    			metadata {
        			name
    				value
              	}
                name
            }
            name
            object_key
            owner
            relations {
                connection {
                    src_field
                    target_field
                }
                connection_expr {
                    sql
                }
                cross_filtering
                rel_join_type
                rel_type
                target_entity
            }
            tags {
                key
                value
                source
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Get Entity Field By Name">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `entity_name`: The name of the entity to retrieve the field from
    * `name`: The name of the field to retrieve

    ```graphql GraphQL Query theme={null}
    query getEntityFieldByName($entity_name: String!, $name: String!) {
        field(entity_name: $entity_name, name: $name) {
            description
            display_name
            error {
                description
            }
            folder
            generated_display_name
            generated_folder_name
            git_url
            hidden
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            tags {
                key
                value
                source
            }
            ui_url
            ... on CalcAttribute {
                owner
                datatype
                sql
            }
            ... on DataSet {
              	dataset_type
              	owner
                sql
            }
            ... on DataSetAttribute {
              	column
              	dataset
                datatype
            }
            ... on Metric {
                datatype
                owner
                sql
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="List Domains">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Query theme={null}
    query {
        domains {
            ai_description
            description
            display_name
            error {
                description
            }
            filters {
                name
                sql
            }
            generated_display_name
            git_url
            hidden
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            parameters {
                description
                name
                value
            }
            source_filters {
                name
                sql
            }
            tags {
                key
                value
                source
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Get Domain By Name">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `name`: The name of the domain to retrieve

    ```graphql GraphQL Query theme={null}
    query getDomainByName($domain_name: String!) {
        domain(name: $domain_name) {
            ai_description
            description
            display_name
            error {
                description
            }
            filters {
                name
                sql
            }
            generated_display_name
            git_url
            hidden
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            parameters {
                description
                name
                value
            }
            source_filters {
                name
                sql
            }
            tags {
                key
                value
                source
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="List Global Parameters">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Query theme={null}
    query {
        parameters {
            description
            display_name
            error {
                description
            }
            generated_display_name
            git_url
            hidden
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            tags {
                key
                value
                source
            }
            value
        }
    }
    ```
  </Accordion>

  <Accordion title="Get Global Parameter By Name">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `name`: The name of the global parameter to retrieve

    ```graphql GraphQL Query theme={null}
    query getGlobalParameterByName($parameter_name: String!) {
        parameter(name: $parameter_name) {
            description
            display_name
            error {
                description
            }
            generated_display_name
            git_url
            hidden
            labels
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            name
            object_key
            owner
            tags {
                key
                value
                source
            }
            value
        }
    }
    ```
  </Accordion>

  <Accordion title="List Dynamic Datasets">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    ```graphql GraphQL Query theme={null}
    query {
        dynamic_datasets {
            ai_description
            attributes
            description
            display_name
            error {
                description
            }
            filters
            generated_display_name
            git_url
            hidden
            labels
            limit
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            metrics
            name
            object_key
            offset
            order {
                alias
                nulls_first
                order
                position
            }
            owner
            parameters {
                description
                name
                value
            }
            tags {
                key
                value
                source
            }
            transform_sql
            use_cache
        }
    }
    ```
  </Accordion>

  <Accordion title="Get Dynamic Dataset By Name">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `name`: The name of the dynamic dataset to retrieve

    ```graphql GraphQL Query theme={null}
    query getDynamicDatasetByName($dynamic_dataset_name: String!) {
        dynamic_dataset(name: $dynamic_dataset_name) {
            ai_description
            attributes
            description
            display_name
            error {
                description
            }
            filters
            generated_display_name
            git_url
            hidden
            labels
            limit
            metadata {
                metadata {
                    name
                    value
                }
                name
            }
            metrics
            name
            object_key
            offset
            order {
                alias
                nulls_first
                order
                position
            }
            owner
            parameters {
                description
                name
                value
            }
            tags {
                key
                value
                source
            }
            transform_sql
            use_cache
        }
    }
    ```
  </Accordion>
</AccordionGroup>

### Validate a Workspace

Use these queries to validate a workspace in a CI/CD pipeline: reload the branch from Git,
confirm the workspace loads, then check every object for errors. This is the same sequence
run by the [GitHub Action](/docs/governance/ci-cd/github-actions); see
[CI/CD Overview](/docs/governance/ci-cd/overview) for using it with other CI/CD systems.

All calls below require the `X-Honeydew-Workspace` and `X-Honeydew-Branch` headers, and the
**Viewer** role or higher. A pipeline runs them in the order shown and fails the step if any
error is found.

**1. Reload the branch from Git** so validation reflects the latest commit of the branch:

```graphql GraphQL Mutation theme={null}
mutation { reset_workspace }
```

**2. Check the workspace for load errors.** If the workspace fails to load (for example, a
YAML parse error), the per-object checks are not meaningful — report these errors first:

```graphql GraphQL Query theme={null}
query {
    workspaces {
        name
        branch
        errors {
            description
        }
    }
}
```

**3. Check objects for validation errors.** This query returns every entity, so that
field-level errors surface even inside otherwise-valid entities. Domains, perspectives, and
parameters use the `has_errors: true` argument, so they return only the objects that fail
validation. Treat the workspace as failing if any entity has a non-null `error`, any entity
returns `fields`, or any domain, perspective, or parameter is returned:

```graphql GraphQL Query theme={null}
query {
    entities {
        name
        error {
            description
        }
        fields(has_errors: true) {
            name
            error {
                description
            }
        }
    }
    domains(has_errors: true) {
        name
        error {
            description
        }
    }
    perspectives(has_errors: true) {
        name
        error {
            description
        }
    }
    parameters(has_errors: true) {
        name
        error {
            description
        }
    }
}
```

**4. Check context items and agents.** Context items (instructions and memories) and agents
report errors under `validation_errors`; both use `has_errors: true`, so any returned object
is a failure:

```graphql GraphQL Query theme={null}
query {
    context_items(has_errors: true) {
        __typename
        ... on InstructionFrontmatter {
            path
            validation_errors {
                error
            }
        }
        ... on MemoryFrontmatter {
            path
            validation_errors {
                error
            }
        }
    }
    agents(has_errors: true) {
        path
        validation_errors {
            error
        }
    }
}
```

### Modifying Schema

<AccordionGroup>
  <Accordion title="Create Object">
    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `yaml`: The YAML definition of the object to create. See references for YAML schema [here](/docs/yaml-schema).
    * `force_with_error`:
      * If **false**, the mutation will fail if the deletion causes the workspace to become invalid
        (For example, if the object is used by another object in the workspace).
      * If **true**, the mutation will delete the object even if it causes the workspace to become invalid.
        This is useful if you are performing a set of changes that will eventually make the workspace valid again.

    **Return Value:**

    The mutation returns the created object, or an error if the creation failed.
    You can use qualifiers to get specific fields of the object, such as `name`, `error`, etc.

    ```graphql GraphQL Mutation theme={null}
    mutation createFromYAML($yaml: String!, $force_with_error: Boolean!) {
        create_object(yaml_text: $yaml, force_with_error: $force_with_error) {
            ... on Field {
                name
                error {
                    description
                }
            }
            ... on Entity {
                name
                error {
                    description
                }
            }
            ... on Perspective {
                name
                error {
                    description
                }
            }
            ... on GlobalParameter {
                name
                error {
                    description
                }
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Update Object">
    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `yaml`: The YAML definition of the object to update. See references for YAML schema [here](/docs/yaml-schema).
    * `object_key`: The key of the object to update. This is the `object_key` field that can be retrieved in any query on objects.
    * `force_with_error`:
      * If **false**, the mutation will fail if the deletion causes the workspace to become invalid
        (For example, if the object is used by another object in the workspace).
      * If **true**, the mutation will delete the object even if it causes the workspace to become invalid.
        This is useful if you are performing a set of changes that will eventually make the workspace valid again.

    **Return Value:**

    The mutation returns the updated object, or an error if the update failed.
    You can use qualifiers to get specific fields of the object, such as `name`, `error`, etc.

    ```graphql GraphQL Mutation theme={null}
    mutation updateFromYAML($yaml: String!, $object_key: String!, $force_with_error: Boolean!) {
        update_object(yaml_text: $yaml, object_key: $object_key, force_with_error: $force_with_error) {
            ... on Field {
                name
                error {
                    description
                }
            }
            ... on Entity {
                name
                error {
                    description
                }
            }
            ... on Perspective {
                name
                error {
                    description
                }
            }
            ... on Domain {
                name
                error {
                    description
                }
            }
            ... on GlobalParameter {
                name
                error {
                    description
                }
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Delete Object">
    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `object_key`: The key of the object to delete.
    * `force_with_error`:
      * If **false**, the mutation will fail if the deletion causes the workspace to become invalid
        (For example, if the object is used by another object in the workspace).
      * If **true**, the mutation will delete the object even if it causes the workspace to become invalid.
        This is useful if you are performing a set of changes that will eventually make the workspace valid again.

    ```graphql GraphQL Mutation theme={null}
    mutation deleteObject($object_key: String, $force_with_error: Boolean!) {
        delete_object(object_key: $object_key, force_with_error: $force_with_error)
    }
    ```
  </Accordion>
</AccordionGroup>

### Deployment

<AccordionGroup>
  <Accordion title="Deploy Dynamic Dataset">
    Deploy a [dynamic dataset](/docs/dynamic-datasets) according to its deployment settings.
    Use this for [aggregate aware caching](/docs/performance/aggregate-awareness) and
    [incremental aggregate updates](/docs/performance/aggregate-incremental-updates).

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `perspective_name`: The name of the dynamic dataset to deploy

    **Return Value:**
    Returns the SQL query used to select from the deployed dynamic dataset.

    ```graphql GraphQL Mutation theme={null}
    mutation deployDynamicDataset($perspective_name: String!) {
        deploy_perspective(perspective_name: $perspective_name)
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "deploy_perspective": "SELECT ... FROM db.schema.my_dataset"
      }
    }
    ```
  </Accordion>

  <Accordion title="Deploy Entity">
    Deploy an entity according to its deployment settings,
    to update the [entity cache](/docs/performance/entity-caching).

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `entity_name`: The name of the entity to deploy

    **Return Value:**
    Returns the SQL query used to select from the deployed entity cache.

    ```graphql GraphQL Mutation theme={null}
    mutation deployEntity($entity_name: String!) {
        deploy_entity(entity_name: $entity_name)
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "deploy_entity": "SELECT ... FROM db.schema.my_entity_cache"
      }
    }
    ```
  </Accordion>

  <Accordion title="Refresh Dynamic Dataset Data">
    Refresh the data for a dynamic dataset that has already been deployed.

    * For **views**: no-op, returns `false`.
    * For **tables**: redeploys the table with fresh data, returns `true`.
    * For **dynamic tables** (Snowflake only): triggers an incremental refresh, returns `true`.

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Parameters:**

    * `perspective_name`: The name of the dynamic dataset to refresh

    **Return Value:**
    Returns `true` if data was refreshed, `false` if no refresh was needed.

    ```graphql GraphQL Mutation theme={null}
    mutation refreshDynamicDataset($perspective_name: String!) {
        refresh_data_for_perspective(perspective_name: $perspective_name)
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "refresh_data_for_perspective": true
      }
    }
    ```
  </Accordion>

  <Accordion title="Clear Deployed Cache Status">
    Clears the deployed cache status so Honeydew re-evaluates cache validity on the next query.

    <Note>
      Honeydew scans the data warehouse information schema to check the
      validity of caches. If an entity or dynamic dataset used for caching
      was rebuilt or replaced outside Honeydew
      (for example, via a third-party tool), call this mutation to notify
      Honeydew that the cache was updated.
    </Note>

    **Workspace/Branch Headers:** Required

    **Permissions:** Editor or higher

    **Return Value:**
    Returns `null`.

    ```graphql GraphQL Mutation theme={null}
    mutation clearDeployedCacheStatus {
        clear_deployed_cache_status
    }
    ```

    ```json Result Example theme={null}
    {
      "data": {
        "clear_deployed_cache_status": null
      }
    }
    ```
  </Accordion>
</AccordionGroup>

### Queries

<AccordionGroup>
  <Accordion title="Get SQL for adhoc query">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `yaml_text`: YAML definition of a dynamic dataset, which represents a query.
      For more information on the YAML format, see [Dynamic Dataset YAML](/docs/dynamic-datasets#yaml-schema).

      Here's an example of a simple dynamic dataset YAML:

      ```yaml theme={null}
      type: perspective
      name: sample_query
      domain: sales
      attributes:
        - customers.customer_id
      metrics:
        - orders.total_sales
      filters:
        - orders.order_date >= '2025-01-01'
      ```

    **Return Value:**

    * `domain`: The domain to use for the query (if applicable), as extracted from the SQL query.
    * `dwh_role`: The Snowflake role to use for the query, based on the definitions in the workspace, branch and the domain.
    * `dwh_warehouse`: The Snowflake warehouse to use for the query, based on the definitions in the workspace, branch and the domain.
    * `sql`: A list of the actual Snowflake SQL queries to run, translated from the provided SQL query by the Honeydew semantic layer.
      Note that there can be multiple sql statements to run, for example - there might be a `SET` statement to set values for parameters used in the sql query.

    ```graphql GraphQL Query theme={null}
    query getSqlFromYaml($yaml_text:String!) {
        get_sql_from_yaml(yaml_text: $yaml_text, domain: $domain) {
            domain
            dwh_role
            dwh_warehouse
            sql
        }
    }
    ```
  </Accordion>

  <Accordion title="Translate SQL interface query to Snowflake SQL">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `sql`: The SQL query to translate. This should be a valid SQL query in **Trino** dialect.
      For more information, see [SQL Interface](/docs/integration/sql-interface) documentation.

      Here's an example of a simple sql query to translate:

      ```sql theme={null}
        SELECT
            "customers.customer_id",
            AGG("orders.total_sales")
        FROM "domains"."sales"
        WHERE "orders.order_date" >= '2025-01-01'
        GROUP BY 1
        ORDER BY 1 DESC
        LIMIT 30
      ```

    **Return Value:**

    * `domain`: The domain to use for the query (if applicable), as extracted from the SQL query.
    * `dwh_role`: The Snowflake role to use for the query, based on the definitions in the workspace, branch and the domain.
    * `dwh_warehouse`: The Snowflake warehouse to use for the query, based on the definitions in the workspace, branch and the domain.
    * `sql`: A list of the actual Snowflake SQL queries to run, translated from the provided SQL query by the Honeydew semantic layer.
      Note that there can be multiple sql statements to run, for example - there might be a `SET` statement to set values for parameters used in the sql query.

    ```graphql GraphQL Query theme={null}
    query adhocSql($sql: String!) {
        adhoc_sql(sql: $sql) {
            domain
            dwh_role
            dwh_warehouse
            sql
        }
    }
    ```
  </Accordion>
</AccordionGroup>

### AI

<AccordionGroup>
  <Accordion title="Plaintext To Data Using AI">
    This query allows you to ask a question to the AI and get a response in the form of a dynamic dataset
    and a SQL query.
    You can use this to ask questions about your data and get a response in a structured format.
    You can subsequently run the SQL query to get the data.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `question`: The data question to ask the AI
    * `domain_name`: The name of the domain to use for the question
    * `llm_name`: The name of the LLM to use for the question,
      or `null` to use the default LLM configured in the domain.
      This will use the model provider or runner configured for the workspace.
    * `default_results_limit`: The default limit for the number of results to return
    * `temperature`: The temperature to use for the LLM response.
      Pass `null` to use the default temperature configured.
    * `max_tokens`: The maximum number of tokens to return in the LLM response.
      Pass `null` to use the default max tokens configured.
    * `conversation_id`: The ID of the conversation to use for the question.
      Can be used in subsequent questions to continue the conversation with follow-up questions.
      Subsequent questions with same `conversation_id` will use the context of the entire thread.
      If `null` is provided, a new conversation will be created.
    * `include_judge`:
      If `true`, the response will include an explanation and correctness evaluation of the LLM response.

    **Return Value:**

    * `error`: An error message if the question failed, or `null` if the question succeeded.
    * `input_tokens`: The number of input tokens used by the LLM.
    * `judge`: An object containing the explanation and correctness evaluation of the LLM response, if `include_judge` is `true`.
      * `explanation`: The explanation of the LLM response.
      * `is_correct`: A status indicating whether the LLM response is correct.
        Can be `yes`, `no`, `partially` or `unknown`.
      * `runtime_ms`: The runtime of the LLM response in milliseconds.
    * `llm_response`: The raw LLM response as a string.
    * `llm_response_json`: The LLM response as a JSON object, if applicable.
    * `output_tokens`: The number of output tokens generated by the LLM.
    * `dynamic_dataset`: The dynamic dataset generated by the LLM response, if applicable.
    * `question_id`: The ID of the question.
    * `runtime_ms`: The runtime of the question in milliseconds.
    * `sql`: The SQL query generated by the LLM response, if applicable.

    ```graphql GraphQL Query theme={null}
    query askQuestion(
            $question: String!, $domain_name: String,
            $llm_name: String, $default_results_limit: Int,
            $temperature: Float, $max_tokens: Int,
            $conversation_id: String, $include_judge: Boolean!) {
        ask_question(
                question: $question, history: null, domain_name: $domain_name,
                prompt_template: null, llm_name: $llm_name,
                default_results_limit: $default_results_limit,
                temperature: $temperature, max_tokens: $max_tokens,
                conversation_id: $conversation_id) {
            error
            input_tokens
            judge @include(if: $include_judge) {
                explanation
                is_correct
                runtime_ms
            }
            llm_response
            llm_response_json
            output_tokens
            dynamic_dataset {
                attributes
                filters
                limit
                metrics
                offset
                order {
                    alias
                    nulls_first
                    order
                    position
                }
                transform_sql
                yaml
            }
            question_id
            runtime_ms
            sql
        }
    }
    ```
  </Accordion>

  <Accordion title="Create Chat for Deep Analysis Questions">
    This mutation creates a new chat session for deep analysis questions.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `agent`: **Required.** The name of the [agent](/docs/integration/context-layer/agents)
      to run the analysis with. The agent supplies both the domain to query and the
      context items loaded into the session.
    * `show_charts`: Whether the analysis produces charts. Defaults to `true`.

    **Return Value:**

    * `chat_id`: The ID of the created chat session
    * `domain`: The domain the agent is scoped to
    * `ui_url`: The URL of the chat in the Honeydew UI

    ```graphql GraphQL Query theme={null}
    mutation createDeepAnalysisChat(
            $agent: String!, $show_charts: Boolean) {
        create_chat(agent: $agent, show_charts: $show_charts) {
            chat_id
            domain
            ui_url
        }
    }
    ```

    To find the agent name to pass, list the agents in the workspace along with
    the domain each one is built on:

    ```graphql GraphQL Query theme={null}
    query listAgents {
        agents {
            agent {
                name
                display_name
                description
                domain
            }
        }
    }
    ```
  </Accordion>

  <Accordion title="Ask Deep Analysis Questions">
    This mutation runs a multi-step agentic analysis
    question, using the semantic layer as the
    source of truth.
    It blocks until the analysis completes
    (up to 5 minutes).

    The response includes markdown text, tabular data,
    and chart visualizations produced during
    the analysis.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `chat_id`: The ID of the conversation
      to use for the question
    * `question`: The deep analysis question
      to ask the AI

    **Return Value:**

    * `response`: A list of content items produced
      by the analysis. Each item is one of:
      * `MarkdownContent`: Textual analysis with
        `text` and `category`
        (`final_conclusion`, `interpretation`,
        `plan`, or `user_response`)
      * `DataContent`: Tabular data with `results`
        (columns and rows)
      * `GraphContent`: A chart. `vega_lite` is a
        complete Vega-Lite specification with the
        data embedded, so it renders as-is.
        `visualization_hint` describes the intended
        chart in natural language, and `group_name`
        groups related content. Also select `data`
        to get the rows on their own, to render with
        a different charting library.
    * `suggested_responses`: A list of suggested
      follow-up questions
    * `ui_url`: The URL of the chat in the
      Honeydew UI

    ```graphql GraphQL Query theme={null}
    mutation askDeepAnalysisQuestion(
            $chat_id: ChatId!,
            $question: String!) {
        ask_deep_analysis_question_sync(
                chat_id: $chat_id,
                question: $question) {
            response {
                ... on MarkdownContent {
                    text
                    category
                }
                ... on DataContent {
                    results {
                        columns { name type }
                        data { values }
                        sql
                    }
                    total_row_count
                    group_name
                }
                ... on GraphContent {
                    vega_lite
                    visualization_hint
                    group_name
                }
            }
            suggested_responses
            ui_url
        }
    }
    ```
  </Accordion>

  <Accordion title="Abort Deep Analysis Chat">
    This mutation aborts a running deep analysis chat,
    stopping any in-progress analysis.
    Use it to cancel a long-running question
    before it completes.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `chat_id`: The ID of the chat session to abort

    **Return Value:**

    * `null` on success
    * `FailureResult` with `error_code` and `message` on error

    ```graphql GraphQL Query theme={null}
    mutation abortDeepAnalysisChat(
            $chat_id: ChatId!) {
        abort_chat(chat_id: $chat_id) {
            error_code
            message
        }
    }
    ```
  </Accordion>

  <Accordion title="List AI Question History" id="list-ai-question-history">
    Returns a paginated list of AI questions asked in the workspace,
    with filtering support.

    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `limit`: Maximum number of results to return (up to 1000)
    * `offset`: Number of results to skip for pagination
    * `params`: Optional filter parameters:
      * `domain`: Filter by domain name(s)
      * `llm_model`: Filter by LLM model name(s)
      * `conversation_id`: Filter by conversation ID(s)
      * `asked_by`: Filter by user display name(s)
      * `client`: Filter by client name(s)
      * `agent`: Filter by agent name(s)
      * `status`: Filter by response status (`FINISHED` or `FAILED`)
      * `from_execution_time`: Filter by start time (inclusive)
      * `to_execution_time`: Filter by end time (inclusive)
      * `question`: Filter by question text (partial match)
      * `llm_response`: Filter by LLM response text (partial match)
      * `has_feedback`: Filter to questions whose chat has user feedback

    **Return Value:**

    A list of `AnalystResponse` objects. Each object includes:

    * `question_id`: Unique ID for the question
    * `response_type`: `QUICK_ANALYSIS` or `DEEP_ANALYSIS`
    * `question`: The question text
    * `asked_by`: Display name of the user who asked the question
    * `client`: The client identifier set in the `X-Honeydew-Client` header
    * `agent`: The agent that handled the question, if applicable
    * `conversation_id`: The ID of the deep analysis chat this question belongs to
    * `execution_time`: When the question was executed
    * `creation_time`: When the question record was created
    * `llm_model`: The LLM model used to answer the question
    * `status`: `FINISHED` or `FAILED`
    * `sql`: The generated SQL, if applicable
    * `error`: Error message if the question failed
    * `runtime_ms`: Total time to answer the question, in milliseconds
    * `chat_title`: The title of the deep analysis chat, if applicable
    * `user_feedback`: User feedback submitted on the chat, if applicable

    ```graphql GraphQL Query theme={null}
    query listAIHistory(
            $limit: NonNegativeInt!,
            $offset: NonNegativeInt,
            $params: AIHistoryParamsInput) {
        ai_history(limit: $limit, offset: $offset, params: $params) {
            question_id
            response_type
            question
            asked_by
            client
            agent
            conversation_id
            execution_time
            creation_time
            llm_model
            status
            sql
            error
            runtime_ms
            chat_title
            user_feedback
        }
    }
    ```

    ```json Example: Filter by feedback theme={null}
    {
      "limit": 50,
      "offset": 0,
      "params": {
        "has_feedback": true,
        "from_execution_time": "2025-01-01T00:00:00Z",
        "to_execution_time": "2025-12-31T23:59:59Z"
      }
    }
    ```
  </Accordion>
</AccordionGroup>

### Publish to BI Tools

<AccordionGroup>
  <Accordion title="Get Looker LookML For Domain">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `domain`: The domain to retrieve the Looker LookML for

    **Return Value:**
    Returns the Looker LookML for the domain as a string.
    For more information, see the [Looker Metadata Sync](/docs/integration/bi-tools/looker#metadata-sync) documentation.

    ```graphql GraphQL Query theme={null}
    query lookmlModel($domain: String) {
        lookml_model(domain: $domain)
    }
    ```
  </Accordion>

  <Accordion title="Get ThoughtSpot TML For Domain">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `domain`: The domain to retrieve the ThoughtSpot TML for
    * `connection_name`: The name of the Honeydew connection in ThoughtSpot to use

    **Return Value:**
    Returns the ThoughtSpot TML for the domain as a string.
    For more information, see the [ThoughtSpot Metadata Sync](/docs/integration/bi-tools/thoughtspot#metadata-sync) documentation.

    ```graphql GraphQL Query theme={null}
    query thoughtSpotTML($domain: String, $connection_name: String!) {
        thoughtspot_tml(domain: $domain, connection_name: $connection_name)
    }
    ```
  </Accordion>

  <Accordion title="Get Lightdash Model For Domain">
    **Workspace/Branch Headers:** Required

    **Permissions:** Viewer or higher

    **Parameters:**

    * `domain`: The domain to retrieve the Lightdash model for

    **Return Value:**
    Returns the Lightdash model for the domain as a string.
    For more information, see the [Lightdash Metadata Sync](/docs/integration/bi-tools/lightdash#metadata-sync) documentation.

    ```graphql GraphQL Query theme={null}
    query lightdashDbtModel($domain: String) {
        lightdash_dbt_model(domain: $domain)
    }
    ```
  </Accordion>
</AccordionGroup>

**Missing an API query or mutation?**

If you need a specific query or mutation that is not covered in this guide,
please reach out to [support@honeydew.ai](mailto:support@honeydew.ai)
