Skip to main content
Honeydew provides a GraphQL API, that allows to directly call the Honeydew service.
This guide covers a direct connection to the Honeydew API using GraphQL.It is also possible to use Honeydew APIs with a Snowflake Connection, by calling the Snowflake Native Application API.
Public GraphQL API is not enabled by default. To enable for your organization, please contact support@honeydew.ai.

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. You cannot use the GraphQL API with a Honeydew username and password.
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.
It is recommended to restrict API access to specific IP addresses or ranges, by using the IP Access Control feature. To set up IP Access Control, please contact support@honeydew.ai.

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)
Monitor these headers in your API responses to implement proper rate limiting in your applications and avoid hitting rate limits unexpectedly.
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.
If you need to increase your rate limits beyond the default, please contact support@honeydew.ai to discuss your requirements.

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.
To learn more about GraphQL, you can refer to the GraphQL documentation
  • Python
  • JavaScript
  • cURL
This example uses the requests library to make HTTP requests to the Honeydew API. To install it, run:
pip install requests
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}}
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.

GraphQL API Reference

Workspaces and Branches

Workspace/Branch Headers: Not requiredPermissions: Viewer or higher
GraphQL Query
query {
  workspaces {
    branch
    dwh_connector_name
    errors {
      description
    }
    git_url
    name
    object_key
  }
}
This mutation creates a new branch in the specified workspace.Workspace/Branch Headers: Not requiredPermissions: Editor or higher
GraphQL Mutation
mutation createWorkspaceBranch($workspace_name: String!, $branch_name: String!) {
    create_workspace_branch(
        workspace_name: $workspace_name
        branch_name: $branch_name
    )
}
Successful Result Example
{
  "data": {
    "create_workspace_branch": null
  }
}
Error Example
{
  "data": {
    "create_workspace_branch": null
  },
  "errors": [
    {
      "locations": [
        {
          "column": 3,
          "line": 2
        }
      ],
      "message": "Workspace \"tpchaa\" is not found",
      "path": [
        "create_workspace_branch"
      ]
    }
  ]
}
This mutation reloads the specified workspace from Git.Workspace/Branch Headers: RequiredPermissions: Viewer or higher
GraphQL Mutation
mutation reloadWorkspace {
    reset_workspace
}
Result Example
{
  "data": {
    "reset_workspace": null
  }
}
This mutation reloads all workspaces from Git.Workspace/Branch Headers: Not requiredPermissions: Viewer or higher
GraphQL Mutation
mutation reloadAllWorkspaces {
    reset_all_workspaces
}
Result Example
{
  "data": {
    "reset_all_workspaces": null
  }
}
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: RequiredPermissions: Admin
GraphQL Mutation
mutation reloadWorkspaceAllUsers {
    reset_workspace_all_users
}
Result Example
{
  "data": {
    "reset_workspace_all_users": null
  }
}
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 requiredPermissions: Admin
GraphQL Mutation
mutation reloadAllWorkspacesAllUsers {
    reset_all_workspaces_all_users
}
Result Example
{
  "data": {
    "reset_all_workspaces_all_users": null
  }
}

Querying Schema

Workspace/Branch Headers: RequiredPermissions: Viewer or higher
GraphQL Query
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
            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
        }
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • entity_name: The name of the entity to retrieve
GraphQL Query
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
        }
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • entity_name: The name of the entity to retrieve the field from
  • name: The name of the field to retrieve
GraphQL Query
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
        ui_url
        ... on CalcAttribute {
            owner
            datatype
            sql          
        }
        ... on DataSet {
          	dataset_type
          	owner
            sql
        }
        ... on DataSetAttribute {
          	column  
          	dataset
            datatype
        }
        ... on Metric {
            datatype
            owner
            sql
        }
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higher
GraphQL Query
query {
    domains {
        ai_description
        description
        display_name
        error {
            description
        }
        filters
        generated_display_name
        git_url
        hidden
        labels
        metadata {
            metadata {
                name
                value
            }
            name
        }
        name
        object_key
        owner
        parameters {
            description
            name
            value
        }
        source_filters
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • name: The name of the domain to retrieve
GraphQL Query
query getDomainByName($domain_name: String!) {
    domain(name: $domain_name) {
        ai_description
        description
        display_name
        error {
            description
        }
        filters
        generated_display_name
        git_url
        hidden
        labels
        metadata {
            metadata {
                name
                value
            }
            name
        }
        name
        object_key
        owner
        parameters {
            description
            name
            value
        }
        source_filters
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higher
GraphQL Query
query {
    parameters {
        description
        display_name
        error {
            description
        }
        generated_display_name
        git_url
        hidden
        labels
        metadata {
            metadata {
                name
                value
            }
            name
        }
        name
        object_key
        owner
        value
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • name: The name of the global parameter to retrieve
GraphQL Query
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
        value
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higher
GraphQL Query
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
        }
        transform_sql
        use_cache
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • name: The name of the dynamic dataset to retrieve
GraphQL Query
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
        }
        transform_sql
        use_cache
    }
}

Modifying Schema

Workspace/Branch Headers: RequiredPermissions: Editor or higherParameters:
  • yaml: The YAML definition of the object to create. See references for YAML schema here.
  • 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 Mutation
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
            }
        }
    }
}
Workspace/Branch Headers: RequiredPermissions: Editor or higherParameters:
  • yaml: The YAML definition of the object to update. See references for YAML schema here.
  • 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 Mutation
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
            }
        }
    }
}
Workspace/Branch Headers: RequiredPermissions: Editor or higherParameters:
  • 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 Mutation
mutation deleteObject($object_key: String, $force_with_error: Boolean!) {
    delete_object(object_key: $object_key, force_with_error: $force_with_error)
}

Queries

Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • yaml_text: YAML definition of a dynamic dataset, which represents a query. For more information on the YAML format, see Dynamic Dataset YAML.
  • domain: The name of the domain to use for the query.
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 Query
query getSqlFromYaml($yaml_text:String!, $domain: String) {
    get_sql_from_yaml(yaml_text: $yaml_text, domain: $domain) {
        domain
        dwh_role
        dwh_warehouse
        sql
    }
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • sql: The SQL query to translate. This should be a valid SQL query in Trino dialect. For more information, see SQL Interface documentation.
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 Query
query adhocSql($sql: String!) {
    adhoc_sql(sql: $sql) {
        domain
        dwh_role
        dwh_warehouse
        sql
    }
}

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: RequiredPermissions: Viewer or higherParameters:
  • question: The data question to ask the AI
  • domain_name: The name of the domain to use for the question
  • cortex_llm_name: The name of the LLM to use for the question, or null to use the default LLM configured in the domain.
  • 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 Query
query askQuestion(
        $question: String!, $domain_name: String,
        $cortex_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, cortex_llm_name: $cortex_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
    }
}

BI Integration

Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • 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 documentation.
GraphQL Query
query lookmlModel($domain: String) {
    lookml_model(domain: $domain)
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • 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 documentation.
GraphQL Query
query thoughtSpotTML($domain: String, $connection_name: String!) {
    thoughtspot_tml(domain: $domain, connection_name: $connection_name)
}
Workspace/Branch Headers: RequiredPermissions: Viewer or higherParameters:
  • 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 documentation.
GraphQL Query
query lightdashDbtModel($domain: String) {
    lightdash_dbt_model(domain: $domain)
}
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