Skip to main content
Embed Ana directly into your own application using an iframe, or access her programmatically via the TextQL API. This guide covers authentication, access control, API usage, and security.

Quick Start

The fastest way to embed Ana is an iframe with an API key.
1

Create an API key

Go to Settings > Developers > Personal API Keys and click Create API key. Copy it immediately — the full key is only shown once.
2

Test the embed URL

Open this URL in an incognito window to confirm the key works:
https://app.textql.com/embed?authKey=YOUR_API_KEY
3

Add the iframe to your app

<iframe
  src="https://app.textql.com/embed?authKey=YOUR_API_KEY"
  width="100%"
  height="600px"
  frameBorder="0"
  allow="clipboard-write"
></iframe>
Ana embedded in an application via iframe
For production, never expose a long-lived API key in frontend code. See Security for the recommended architecture.

Authentication

Personal API Keys vs Service Accounts

TextQL has two types of identities for programmatic access:
Personal API KeyService Account Key
Acts asYouA dedicated bot identity
RolesYour roles (can change over time)Fixed at creation (immutable)
Best forDev, testing, scriptsProduction embeds, automations
Survives employee turnoverNoYes
Personal API Keys — Go to Settings > Developers > Personal API Keys. You can optionally set a key name, expiry (e.g., 3600 for 1 hour), and assumed roles.
Personal API Keys settings page
Service Accounts — Go to Settings > Developers > Service Accounts and click +. Set a name, description, roles (immutable after creation), and owner. Once created, generate API keys from the service account’s detail page — these keys act as the service account, not as you.
Create service account modal
Service account detail page
Admins can view and revoke all keys across the org under Settings > Developers > All API Keys.

Access Control

How Roles Work

Roles control which connectors and context an API key can access. The embedded experience shows exactly the data the key’s identity has access to. Context can be scoped at three levels:
ScopeWho Sees It
OrganizationEveryone in the org
RoleOnly users with that specific role
ConnectorOnly when querying that specific data source
Settings Members Manage Roles page
Assigning Roles to context files in Context Library

Programmatic Role Scoping

Your backend can mint scoped API keys on demand using the CreateApiKey RPC — no separate TextQL user accounts needed per role. Step 1 — List available roles:
curl 'https://app.textql.com/rpc/public/textql.rpc.public.rbac.RBACService/ListRoles' \
  -H 'Content-Type: application/json' \
  -H 'connect-protocol-version: 1' \
  -H 'Authorization: Bearer YOUR_MASTER_API_KEY' \
  --data-raw '{}'
Step 2 — Create a scoped key:
curl 'https://app.textql.com/rpc/public/textql.rpc.public.rbac.RBACService/CreateApiKey' \
  -H 'Content-Type: application/json' \
  -H 'connect-protocol-version: 1' \
  -H 'Authorization: Bearer YOUR_MASTER_API_KEY' \
  --data-raw '{
    "expirySeconds": 3600,
    "assumedRoles": [
      "80de0196-496f-44fe-9d4c-8013b3b44082"
    ]
  }'
The response returns apiKey (for Bearer auth) and apiKeyHash (for embed URLs via ?authKey=HASH). Pattern — mint a scoped key per user session:
def get_embed_for_user(user):
    role_map = {
        "finance": ["uuid-for-finance-role"],
        "marketing": ["uuid-for-marketing-role"],
        "executive": ["uuid-for-finance-role", "uuid-for-marketing-role"],
    }

    resp = requests.post(
        "https://app.textql.com/rpc/public/textql.rpc.public.rbac.RBACService/CreateApiKey",
        headers={
            "Content-Type": "application/json",
            "connect-protocol-version": "1",
            "Authorization": f"Bearer {MASTER_KEY}",
        },
        json={"expirySeconds": 3600, "assumedRoles": role_map[user.role]},
    )

    key_hash = resp.json()["apiKeyHash"]
    return f"https://app.textql.com/embed?authKey={key_hash}"

SSO and Role Mapping

For organizations using SSO (Okta, Azure AD, Ping Identity), roles can be mapped from your identity provider’s groups so new users are automatically assigned the correct TextQL role on first login.
Settings Security Add OIDC Provider dialog

Embedding via iframe

Iframe Attributes

AttributeRecommended ValueNotes
srchttps://app.textql.com/embed?authKey=...Embed URL with API key
width100%Full width of container
height600px or moreAna works best with at least 500px
frameBorder0Clean look with no border
allowclipboard-writeLets users copy Ana’s responses

Query Parameters

All parameters are optional. Absent parameters fall back to the org/role defaults configured in TextQL settings. Authentication & session
ParameterTypeDescription
authKeystringAPI key hash (required unless SSO is configured)
chatIdstringResume an existing chat by ID
displayPartitionstringDisplay partition override
Connector selection
ParameterTypeDescription
connectorIdsstringComma-separated connector IDs to pre-select, e.g., connectorIds=42,99. Takes precedence over connectorId.
connectorIdnumberSingle connector ID (legacy; use connectorIds for multiple)
Tool toggles — each accepts true or false; omit to use the org/role default.
ParameterDescription
sqlEnabledAllow Ana to write and execute SQL
ontologyEnabledAllow Ana to use the semantic ontology layer
pythonEnabledAllow Ana to run Python for analysis and visualization
webSearchEnabledAllow Ana to search the web
googleDriveEnabledAllow Ana to access Google Drive
tableauEnabledAllow Ana to interact with Tableau
powerbiEnabledAllow Ana to interact with Power BI
Example — SQL-only embed locked to two connectors:
<iframe
  src="https://app.textql.com/embed?authKey=YOUR_KEY&connectorIds=42,99&sqlEnabled=true&ontologyEnabled=false&pythonEnabled=false&webSearchEnabled=false"
  width="100%"
  height="600px"
  frameBorder="0"
  allow="clipboard-write"
></iframe>

Embedding in Tableau

  1. In Tableau, create a new workbook and add a dashboard
  2. From the Objects panel, drag a Web Page object onto the dashboard
  3. Enter your embed URL: https://app.textql.com/embed?authKey=YOUR_API_KEY
  4. Resize the Web Page object to fit your layout
Ana embedded in a Tableau dashboard

One-Click Tableau Collection Chats

TextQL supports direct links to start chats with a specific Tableau collection already attached. Generating embed links (Admin only)
  1. Open any chat and click Attach Tableau
  2. Hover over a collection card and click the link icon in the top-left corner
  3. The embed URL is automatically copied to your clipboard
URL format
https://app.textql.com/tableau?authKey=EMBED_USER_KEY&tableauDatasetId=COLLECTION_ID&message=OPTIONAL_MESSAGE
  • authKey — your organization’s Embed User API key (auto-generated)
  • tableauDatasetId — the ID of the Tableau collection to attach
  • message — an optional initial message to auto-send when the chat opens
<iframe
  src="https://app.textql.com/tableau?authKey=EMBED_USER_KEY&tableauDatasetId=COLLECTION_ID"
  width="100%"
  height="600px"
  frameBorder="0"
  allow="clipboard-write"
></iframe>
Embed links use a dedicated service account with restricted permissions. Rotate the Embed User’s API key from Settings → API Keys if compromised.

Embedding in Other BI Tools

The same iframe pattern works in any tool that supports embedded web content:
  • Internal portals — React, Angular, Vue, etc.
  • Confluence / SharePoint — via HTML embed macros
  • Retool / Appsmith — via iframe components

API Reference

All API requests use base URL https://app.textql.com/v1 with a Bearer token in the Authorization header.

Endpoints

EndpointDescription
POST /v1/chatOne-shot chat — send a question, get a complete response
POST /v1/streamStreaming chat — receive response tokens in real-time
POST /v1/chat/getGet details of a specific chat by ID
POST /v1/chat/cancelCancel a running chat
POST /v1/playbooksList, create, update, deploy, delete playbooks
POST /v1/connectorsList configured data sources

One-Shot Chat

Best for backend automations and scripts where you don’t need to show partial results.
{
  "question": "What were total sales last quarter?",
  "chatId": null,
  "tools": {
    "connectorIds": [42],
    "sqlEnabled": true,
    "pythonEnabled": true,
    "ontologyEnabled": true,
    "webSearchEnabled": false
  }
}
  • question — the natural-language question for Ana
  • chatId — pass an existing ID to continue a conversation, or omit to start a new one
  • tools — configure which tools Ana can use (defaults applied if omitted)

Streaming Chat

Uses Connect-RPC to deliver tokens in real-time — ideal for user-facing apps with a live typing experience.
The streaming endpoint requires a Connect-RPC client and cannot be tested with a simple curl. Use the official SDKs.
Stream flow: initialize transport → send StreamRequest → receive metadata → stream text tokens and preview URLs → final QUERY_STATUS_COMPLETE

Client SDKs

pip install textql
from textql import TextQLClient

client = TextQLClient(api_key="YOUR_API_KEY")

tools = {
    "connector_ids": [42],
    "sql_enabled": True,
    "python_enabled": True,
    "ontology_enabled": True,
    "web_search_enabled": False,
}

# Streaming
for response in client.chat.stream(question="Show me revenue by region", tools=tools):
    if response.HasField('text'):
        print(response.text, end='', flush=True)

# One-shot
response = client.chat.create(question="What is our current churn rate?", tools=tools)
print(response.response)

Tool Configuration

ToolTypeDescription
connectorIdsnumber[]Database connector IDs to query
sqlEnabledbooleanAllow Ana to write and execute SQL
pythonEnabledbooleanAllow Ana to run Python for analysis and visualization
ontologyEnabledbooleanAllow Ana to use the semantic ontology layer
webSearchEnabledbooleanAllow Ana to search the web
tableauEnabledbooleanAllow Ana to interact with Tableau
powerbiEnabledbooleanAllow Ana to interact with Power BI
googleDriveEnabledbooleanAllow Ana to access Google Drive
Tool configuration is locked for the duration of a chat. Start a new chat if you need different tools.

Security

The core principle: never expose a long-lived API key in frontend code.
Your Frontend  -->  Your Backend  -->  TextQL API
    ^                    |
    +-- short-lived key -+
Recommended — Short-lived scoped keys (Pattern B): Your backend mints a fresh key per user session via CreateApiKey. Keys expire automatically, each session is auditable, and roles are scoped per key. See the code example above. Most secure — Backend proxy (Pattern A): Your frontend never sees a TextQL key at all. Your backend proxies all API calls, adding the Authorization: Bearer header server-side. Simpler alternative — Role-based static keys (Pattern C): Create a dedicated TextQL user and key per user group. Your backend selects the right key based on the authenticated user’s role. Security checklist:
  • API keys stored server-side only (env vars, secrets manager)
  • Frontend never contains hardcoded API keys
  • Each embed use case has its own dedicated key
  • Keys rotated on a regular schedule and unused keys revoked promptly
  • SSO role mappings configured so new users get appropriate access automatically

Quick Reference

ResourceURL
TextQL Apphttps://app.textql.com
API Base URLhttps://app.textql.com/v1
Embed Base URLhttps://app.textql.com/embed?authKey=...
Full API DocsAPI Reference
SDK DocsClient SDKs
Security WhitepaperSecurity
PricingPricing & Consumption
API usage consumes ACUs just like interactive usage. Each chat sandbox stays warm for 1 hour after last activity (500 ACUs/hour), plus inference costs. See Pricing for the full rate table.