CluedIn Python SDK
On this page
- Getting started
- Authentication
- Import CluedIn Python SDK module
- Creating a Context
- Connecting to CluedIn SaaS
- Booleans in configuration
- Troubleshooting authentication
CluedIn provides powerful REST and GraphQL APIs. To simplify programmatic interaction, we offer the CluedIn Python SDK — a Python package that handles authentication, automation, data import and export, data transformation, and data exploration.
You can use CluedIn Python SDK in many environments, from your local laptop to cloud services like:
- Microsoft Fabric
- Azure Synapse Analytics
- Databricks
- Snowflake
- Azure Functions
- Jupyter Notebook
- Google Colab
- Airflow
- dbt
- Kaggle
The above list is non-exhaustive. You can use CluedIn Python SDK in any environment where you can run Python code.
Some of the scenarios where CluedIn Python SDK will be helpful are:
- Querying data from your CluedIn instance.
- Exporting and saving the data to CSV, Parquet, Excel, JSON, or many other file formats.
- Reading and writing configuration of your CluedIn instance.
- Ingesting data in CluedIn.
- Automating repetitive actions to reduce manual work in UI.
Getting started
CluedIn Python SDK requires Python 3.10 or later (>=3.10,<4.0).
Local environment
When you run Python scripts or notebooks on your local machine, we recommend using virtualenv or venv to ensure your local environment has the right version of Python and installed modules.
To install CluedIn Python SDK, run the following command in your shell:
pip install cluedin
Cloud environments and notebooks
-
To install CluedIn Python SDK in a notebook, use
%pipinstead ofpipand run the following command in your notebook’s cell:%pip install cluedinAlternatively, when you use notebooks in tools like Microsoft Fabric, Databricks, etc., there is usually a way to configure the notebook’s environment. For example, here’s how to install a module in Microsoft Fabric: https://learn.microsoft.com/en-us/fabric/data-engineering/create-and-use-environment.
-
In all cases, after you install the
cluedinpackage, you can import it in your Python code:import cluedin
Authentication
To connect to your CluedIn instance via API or CluedIn Python SDK, you need the following:
-
URL of your CluedIn instance.
-
API (access) token – a JWT token that gives you access to API.
CluedIn Python SDK uses the Context object to keep the information it needs to connect to CluedIn API.
Context settings
You rarely need to set every value. In most cases, you provide domain, org_name, and either an access_token or a user_email/user_password pair – the SDK derives all the URLs from them.
| Setting | Default | Description |
|---|---|---|
domain | – | Everything in the host name after the organization name. For https://foobar.contoso.com, the domain is contoso.com. |
org_name | – | Organization name. It is also the OAuth client_id used when signing in. |
user_email | – | Email address used to sign in. Required for get_token. |
user_password | – | Password used to sign in. Required for get_token. |
access_token | – | JWT access token. Set it directly if you already have one, or let get_token populate it. |
protocol | https | Protocol used to build the URLs below. Keep it as https. |
org_url | {protocol}://{org_name}.{domain} | Base URL of the organization. Every URL below is derived from it. |
auth_url | {org_url}/auth | Authentication endpoint. The token is requested from {auth_url}/connect/token. |
api_url | {org_url}/api/api | REST API endpoint, used by helpers such as cluedin.vocab and cluedin.entity. |
gql_api_url | {api_url}/graphql | GraphQL endpoint used by cluedin.gql.gql, cluedin.gql.entries, and cluedin.gql.search. |
gql_org_url | {org_url}/graphql | Organization-level GraphQL endpoint, used only by cluedin.gql.org_gql. |
public_api_url | {org_url}/public/api | Public API endpoint used by cluedin.public. |
verify_tls | True | Whether to validate the server’s TLS certificate. |
Note that gql_api_url ends in /api/api/graphql, not /graphql. {org_url}/graphql is a different endpoint (gql_org_url) that serves only the organization-level schema, and posting a normal search query to it returns 400 Bad Request.
Import CluedIn Python SDK module
In the code examples below, we assume that you imported CluedIn module in your code:
import cluedin
Creating a Context
From API token
If you already have the API token, CluedIn Python SDK can build the Context for you:
# assuming your API token is in the CLUEDIN_TOKEN variable
ctx = cluedin.Context.from_jwt(CLUEDIN_TOKEN)
Now, you can use the ctx Context variable to call CluedIn APIs.
From an object
You can also create a Context from a Python dict:
# assumming you log in to https://foobar.contoso.com
# "foobar" is org_name, and "contoso.com" is the domain
context = {
"domain": "contoso.com",
"org_name": "foobar",
"access_token": CLUEDIN_TOKEN
}
ctx = cluedin.Context.from_dict(context)
From a file
# cluedin.json
# {
# "domain": "contoso.com",
# "org_name": "foobar",
# "access_token": CLUEDIN_TOKEN
# }
ctx = cluedin.Context.from_json_file("cluedin.json")
Getting API token from email and password
The API token lets you use some of CluedIn APIs like data ingestion endpoints and search, but to have full access to APIs (assuming you have the necessary permissions), you need to use the token that CluedIn gives you when you log in with your email and password. With the CluedIn Python SDK, you can set your email and password in the Context, and then call the get_token method to get the token:
ctx = cluedin.Context.from_dict({
"domain": "contoso.com",
"org_name": "foobar",
"user_email": "joe@contoso.com",
"user_password": "yourStrong(!)Password"
})
ctx.get_token() # after this line, `ctx.access_token` will be set
Connecting to CluedIn SaaS
CluedIn SaaS (multi-tenant) instances follow a fixed host naming pattern. The same server answers on two host names, and it matters which one you use:
https://<org>.<region>.saas.cluedin.com– the UI host for a single organization. This is the address you open in a browser.https://app.<region>.saas.cluedin.com– the API host, shared by every organization in that region. This is the host in theiss(issuer) claim of your token.
<region> is the region code of your instance, for example weu for West Europe. Both host names are covered by the same wildcard certificate, so TLS verification works against either one.
The URL patterns that matter when you configure the SDK are:
| Endpoint | URL pattern |
|---|---|
| Token | https://app.<region>.saas.cluedin.com/auth/connect/token |
| GraphQL | https://app.<region>.saas.cluedin.com/api/api/graphql |
Configuration example
The following configuration works against a SaaS instance as-is. Change only the region, organization name, and credentials:
{
"domain": "weu.saas.cluedin.com",
"org_name": "presales",
"user_email": "joe@cluedin.com",
"user_password": "yourStrong(!)Password",
"verify_tls": true
}
Save it as cluedin.json and load it:
import cluedin
ctx = cluedin.Context.from_json_file("cluedin.json")
ctx.get_token()
# GraphQL
query = 'query { search(query: "*", pageSize: 1) { totalResults } }'
result = cluedin.gql.gql(ctx, query)
# REST
vocab_keys = cluedin.vocab.get_vocab_keys(ctx)
Because domain is everything after the organization name, weu.saas.cluedin.com plus an org_name of presales gives an org_url of https://presales.weu.saas.cluedin.com, and the SDK derives the token and GraphQL URLs from there. You do not need to set api_url or gql_api_url for SaaS.
Do not set "api_url": "app". A snippet with that value circulates in older notebooks, but api_url is a full base URL, not a host prefix, so setting it to app makes every REST call fail with MissingSchema: Invalid URL 'app/entity/schema': No scheme supplied. Likewise, setting "gql_api_url": "https://app.<region>.saas.cluedin.com/graphql" returns 400 Bad Request, because the API GraphQL endpoint is at /api/api/graphql.
Pinning requests to the API host
If you want every call to go to the shared app. host instead of the per-organization host – for example, when only the app. host is allowed through a firewall – set org_url and leave the rest to the SDK:
{
"domain": "weu.saas.cluedin.com",
"org_name": "presales",
"org_url": "https://app.weu.saas.cluedin.com",
"user_email": "joe@cluedin.com",
"user_password": "yourStrong(!)Password"
}
Keep org_name set to your organization even when you pin org_url, because org_name is sent as the OAuth client_id.
Booleans in configuration
verify_tls is the one setting where it is easy to write something that is silently wrong, because Python and JSON spell booleans differently.
In a Python dict, booleans are True and False – capitalized. Writing "verify_tls": false in Python code raises NameError: name 'false' is not defined. In a .json file, it is the opposite: booleans are lowercase true and false, and True is invalid JSON.
Correct in Python:
ctx = cluedin.Context.from_dict({
"domain": "weu.saas.cluedin.com",
"org_name": "presales",
"user_email": "joe@cluedin.com",
"user_password": "yourStrong(!)Password",
"verify_tls": False # Python: False, not false
})
Correct in cluedin.json:
{
"domain": "weu.saas.cluedin.com",
"org_name": "presales",
"user_email": "joe@cluedin.com",
"user_password": "yourStrong(!)Password",
"verify_tls": false
}
Context.from_dict treats any value that is not the string true (case-insensitive) as False. This means "verify_tls": 1 and "verify_tls": "yes" both disable certificate validation instead of enabling it. Use only the boolean literals True/False in Python and true/false in JSON.
When should you set verify_tls to False? Only when the certificate cannot be validated – a self-signed certificate on a development or on-premises instance, or a corporate proxy that intercepts TLS. CluedIn SaaS presents a valid certificate, so leave verify_tls at its default of True there. Turning verification off also makes urllib3 print an InsecureRequestWarning on every call.
Troubleshooting authentication
Most connection problems surface as an exception from ctx.get_token(). The message tells you which part of the configuration is wrong.
invalid_username_or_password
requests.exceptions.HTTPError: 400 Client Error: Bad Request
{"error":"invalid_grant","error_description":"invalid_username_or_password"}
The user_email or user_password is wrong. CluedIn returns the same error for both, so it does not reveal which one failed.
To diagnose:
- Open
https://<org>.<region>.saas.cluedin.comin a browser and sign in with the same credentials. If sign-in fails there, the credentials are the problem. - Check that the password reached Python unchanged. Passwords containing
!,$, or backslashes are frequently mangled by shell interpolation or by an.envfile. Printlen(ctx.user_password)and compare it with the expected length. - If your account signs in through an external identity provider (such as Microsoft Entra ID), the username and password grant does not apply. Get a token from the browser session instead and use
cluedin.Context.from_jwt.
Client not found for client id
requests.exceptions.HTTPError: 500 Server Error: Internal Server Error
Client not found for client id <value>
The org_name does not match an organization on that instance. It must be the organization name exactly as it appears in the host name – for https://presales.weu.saas.cluedin.com, org_name is presales.
ConnectionError or NameResolutionError
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='presales.weu.saas.cluedin.invalid', port=443):
Max retries exceeded with url: /auth/connect/token (Caused by NameResolutionError(...))
The host name built from domain and org_name does not exist. The host name in the error message is the fastest way to see what the SDK actually assembled.
To diagnose:
-
Print the Context –
print(ctx)shows every derived URL, with the password and token masked:Context: Domain: weu.saas.cluedin.com Organization Name: presales Organization URL: https://presales.weu.saas.cluedin.com Authentication URL: https://presales.weu.saas.cluedin.com/auth API URL: https://presales.weu.saas.cluedin.com/api/api GQL API URL: https://presales.weu.saas.cluedin.com/api/api/graphql Verify TLS: True - Compare the Organization URL with the URL you use in the browser. They must match.
- Check that you did not put the whole URL into
domain.domainis only the part after the organization name, without a protocol –weu.saas.cluedin.com, nothttps://presales.weu.saas.cluedin.com.
ConnectTimeout
A timeout on port 80 means protocol was set to http. Remove the setting, or set it to https.
A timeout on port 443 usually means the instance is not reachable from where your code runs – check VPN, firewall rules, and outbound proxy configuration for notebook environments such as Fabric or Databricks.
SSLCertVerificationError
requests.exceptions.SSLError: ... certificate verify failed: unable to get local issuer certificate
The certificate chain cannot be validated. On a development or on-premises instance with a self-signed certificate, set verify_tls to False (false in JSON). On SaaS, this error normally points to a TLS-intercepting corporate proxy – install its root certificate rather than disabling verification.
400 Bad Request from a GraphQL call
Authentication succeeded but the query fails. Check ctx.gql_api_url: it must end in /api/api/graphql. If it ends in just /graphql, you have either set gql_api_url explicitly or set api_url to something that is not a full base URL. Remove both settings and let the SDK derive them.
401 Unauthorized from any call
The token is missing or expired. Context does not refresh tokens automatically, so call ctx.get_token() again in long-running jobs.