:::note Generated reference Generated from honeyframeapi 0.1.8 — do not edit by hand. :::
honeyframeapi.client
The Honeyframe SDK entry point.
HoneyframeClient is constructed once with a base URL + credentials, then
navigates to resource handles (Project,
Dataset,
Dashboard).
import os
import honeyframeapi
client = honeyframeapi.HoneyframeClient(
"https://platform.your-domain.com",
token=os.environ["HONEYFRAME_TOKEN"], # an hf_… Personal Access Token
project_id=1)
df = client.sql("SELECT * FROM marts.fact_orders FETCH FIRST 100 ROWS ONLY")
For interactive use, username= plus password=getpass.getpass() also
works; never hard-code a password in a script.
class HoneyframeClient
HoneyframeClient(base_url: Optional[str] = None, *, token: Optional[str] = None, username: Optional[str] = None, password: Optional[str] = None, auth: Optional[AuthBase] = None, org_id: Optional[int] = None, project_id: Optional[int] = None, timeout: Optional[float] = DEFAULT_TIMEOUT, verify: Union[bool, str, ssl.SSLContext] = True, max_retries: int = DEFAULT_MAX_RETRIES, retry_backoff: float = DEFAULT_RETRY_BACKOFF, allow_insecure_http: Optional[bool] = None, transport: Optional[httpx.BaseTransport] = None)
Authenticated HTTP client + factory for Honeyframe resource handles.
Create a client.
base_url must be https://. Plain http:// is accepted only
for a loopback host (localhost, 127.0.0.1, ::1) or when
allow_insecure_http=True (or HONEYFRAME_ALLOW_INSECURE_HTTP=1
in the environment); otherwise HoneyframeConfigError, because
the bearer token and any login password would travel in clear text.
verify is True (system trust store), a path to a CA bundle
file or directory (for a private CA), or an ssl.SSLContext.
verify=False turns certificate checks off and warns.
timeout is the per-request default in seconds (None = no
timeout); most calls also take their own timeout=. transport
plugs in a custom httpx.BaseTransport (a test double, a
proxy transport). Redirects are never followed, so the Authorization
header cannot be forwarded to another host.
HoneyframeClient.from_env()
@classmethod
from_env(**overrides) -> HoneyframeClient
Build a client entirely from environment variables.
Reads HONEYFRAME_URL/HUB_API_BASE, then the auth + project env
vars resolved by auth.auth_from_kwargs. Any
keyword overrides win.
HoneyframeClient.close()
close() -> None
HoneyframeClient.using()
using(*, org_id: Optional[int] = None, project_id: Optional[int] = None) -> HoneyframeClient
Mutate the org/project scope in place and return self (chainable).
HoneyframeClient.request()
request(method: str, path: str, *, params: Optional[dict] = None, json: Any = None, headers: Optional[dict] = None, project_id: Optional[int] = None, org_id: Optional[int] = None, raw: bool = False, timeout: Any = _DEFAULT, **kw: Any) -> Any
Call any platform endpoint that has no typed method yet.
The supported escape hatch: same auth, org/project headers, retries, 401 re-login and typed exceptions as every handle method:
client.request("GET", "/api/version")
client.request("POST", "/api/some/endpoint", json={...}, timeout=300)
path is relative to base_url and must start with /; an
absolute URL is refused so the token never goes to another host.
Interpolate untrusted values into path yourself with care (they
are NOT encoded here). Extra keyword arguments (files=,
data=, content=) go to httpx.Client.request. Returns
the decoded JSON body (or bytes with raw=True).
HoneyframeClient.stream_chat()
stream_chat(message: str, *, agent_id: Optional[int] = None, session_id: Optional[int] = None, model: Optional[str] = None, persona: Optional[str] = None, system: Optional[str] = None, webapp_key: Optional[str] = None, page_key: Optional[str] = None, history: Optional[list] = None, images: Optional[list] = None, max_tokens: Optional[int] = None, project_id: Optional[int] = None, org_id: Optional[int] = None) -> Iterator[dict]
Stream a chat reply from POST /api/chat/stream as SSE events.
Yields {"event", "data"} dicts in the Honeyframe SSE schema:
token / thinking / tool_start / tool_result /
citation / artifact / usage / error / done. Render
token text as it arrives, or fold the whole stream with
collect_stream:
for ev in client.stream_chat("Top 5 branches by revenue?", persona="director"):
if ev["event"] == "token":
print(ev["data"]["text"], end="", flush=True)
persona selects a capability persona (e.g. director = governed
marts-only); it is intersected server-side with the caller's scopes, so
it can only narrow, never escalate.
images attaches pictures for a vision-capable model — a list of
content parts in the same shape the web/mobile clients send:
images=[{"type": "image_url",
"image_url": {"url": "data:image/png;base64,iVBORw0K..."}}]
Ignored server-side when the resolved model is not vision-capable.
HoneyframeClient.get_auth_info()
get_auth_info() -> dict
Return the current user profile (GET /api/auth/me).
HoneyframeClient.license_status()
license_status() -> dict
License state for the caller's current org (GET /api/license/status).
Returns {"status": …} with status ∈ valid | grace |
expired | missing | invalid. Only valid and grace
pass the platform's lockdown gate — in every other state each endpoint
outside /api/license/* returns 403, so this is the one call worth
making first when a whole script starts failing with auth errors.
When a license resolves, the dict also carries customer, tier,
products, users_limit, max_seats, features, expires,
days_remaining, version and org_slug. grace / expired
/ missing / invalid add a human-readable message.
HoneyframeClient.create_pat()
create_pat(name: str = '', *, expires_days: Optional[int] = PAT_DEFAULT_DAYS) -> dict
Mint an hf_… Personal Access Token.
The full secret is in the returned dict's token field — shown ONCE.
Store it, then authenticate future clients with
HoneyframeClient(url, token="hf_…").
expires_days defaults to 90; 0..730 is accepted and 0 means
the token never expires (opt in deliberately). None sends no
lifetime, so the platform applies its own default (90 days).
HoneyframeClient.list_pats()
list_pats() -> list[dict]
List your active PATs (metadata only — never the secret).
HoneyframeClient.plugin_recipe_types()
plugin_recipe_types() -> list[dict]
Custom recipe types contributed by the plugins your org has enabled
(GET /api/plugins/recipe-types). Each entry:
{type, plugin, display_name, description, params, standalone}. Empty
when no plugins are enabled. Pass a type to
create_plugin_recipe.
HoneyframeClient.revoke_pat()
revoke_pat(token_id: int) -> dict
Revoke one of your PATs.
HoneyframeClient.get_instance_info()
get_instance_info() -> dict
Return the platform version (GET /api/version).
HoneyframeClient.register_node()
register_node(name: str, base_url: str, api_key: str, *, role: str = 'automation') -> dict
Register a remote Honeyframe install (base_url + a PAT issued on
that install) so a bundle can be pushed to it. The PAT is encrypted at
rest and never returned. Returns {node_id, name, base_url, role}.
HoneyframeClient.list_nodes()
list_nodes() -> list[dict]
List registered remote nodes (secrets never included).
HoneyframeClient.delete_node()
delete_node(node_id: int) -> dict
Delete a registered remote node.
HoneyframeClient.list_projects()
list_projects() -> list[dict]
List projects visible to the current user.
HoneyframeClient.get_project()
get_project(project: Union[int, str]) -> Project
Return a Project handle by numeric id or slug.
A slug is resolved against list_projects (matching slug or
name); an int is used directly.
HoneyframeClient.create_project()
create_project(name: str, slug: str, *, description: Optional[str] = None, icon: str = 'folder', color: str = '#B45309') -> Project
Create a project and return its handle.
HoneyframeClient.list_dashboards()
list_dashboards(tab: str = 'all', *, project_id: Optional[int] = None) -> list[dict]
List dashboards (tab ∈ my|shared|all|public).
Scoped to the client's current project; pass project_id to list
another project's (the server checks you can read it).
HoneyframeClient.get_dashboard()
get_dashboard(dashboard_id: int) -> Dashboard
Return a Dashboard handle (fetches detail + cards).
HoneyframeClient.list_card_templates()
list_card_templates() -> list[CardTemplate]
The org's reusable card templates as CardTemplate handles
(org-visible ∪ the caller's private ones).
HoneyframeClient.create_card_template()
create_card_template(name: str, card_type: str, *, sql: str = '', card_config: Optional[dict] = None, description: Optional[str] = None, size_x: int = 12, size_y: int = 4, tags: Optional[list] = None, folder: Optional[str] = None, visibility: Optional[str] = None) -> CardTemplate
Create a reusable card template. visibility ∈ org | private
(default org). Returns its CardTemplate handle.
HoneyframeClient.list_collections()
list_collections() -> list[dict]
Dashboard collections in the current org (each with dashboard_count).
HoneyframeClient.create_collection()
create_collection(name: str, *, parent_id: Optional[int] = None) -> dict
Create a dashboard collection. parent_id nests it under another.
HoneyframeClient.update_collection()
update_collection(collection_id: int, name: str, *, parent_id: Optional[int] = None) -> dict
Rename / re-parent a collection.
HoneyframeClient.delete_collection()
delete_collection(collection_id: int) -> dict
Delete a collection; its dashboards fall back to uncategorized.
HoneyframeClient.list_connectors()
list_connectors(category: Optional[str] = None) -> list[dict]
List configured connectors for the current org.
HoneyframeClient.list_connector_catalog()
list_connector_catalog() -> list[dict]
List the connector types available to configure.
HoneyframeClient.get_connector()
get_connector(connector_id: int) -> Connector
Return a Connector handle.
HoneyframeClient.create_connector()
create_connector(name: str, connector_type: str, *, config: Optional[dict] = None, description: str = '', output_schemas: Optional[list] = None) -> Connector
Create an org-level connector and return its handle.
HoneyframeClient.list_my_credentials()
list_my_credentials() -> list[dict]
The caller's personal credential slots across every per_user-mode
connector in the org, each with fill status and its secret fields
({connector_id, name, connector_type, filled, updated_at, secret_fields}). Fill a slot with
Connector.set_my_credentials.
HoneyframeClient.list_knowledge_bases()
list_knowledge_bases() -> list[dict]
Knowledge Banks visible in the current project (this project's ∪ the org-level ones), each with doc/chunk counts.
HoneyframeClient.get_knowledge_base()
get_knowledge_base(kb_id: int) -> KnowledgeBase
Return a KnowledgeBase handle (fetches its record).
HoneyframeClient.create_knowledge_base()
create_knowledge_base(name: str, *, description: str = '', embedding_model: str = 'text-embedding-3-small', embedding_dimensions: int = 1536, chunk_size: int = 800, chunk_overlap: int = 100, source_folder_id: Optional[int] = None, vector_connector_id: Optional[int] = None, embedding_connector_id: Optional[int] = None) -> KnowledgeBase
Create a Knowledge Bank in the current project and return its handle.
vector_connector_id picks the vector store that holds the embeddings
(faiss / chroma / pinecone / pgvector / the built-in numpy store);
embedding_connector_id picks the embedding provider (openai /
ollama / gemini). Both are optional — a KB with neither stores chunks
but can't be searched until wired + embedded. Discover the eligible
connectors with kb_connector_options.
HoneyframeClient.kb_connector_options()
kb_connector_options() -> dict
Which of the org's connectors can back a Knowledge Bank —
{vector_stores: [...], embedding_providers: [...]}. Derived from the
connector registry, so new backends (e.g. pgvector) appear automatically.
HoneyframeClient.llm_mesh_overview()
llm_mesh_overview() -> dict
Every LLM connection in the org joined with its governance policy and
month-to-date spend/calls, plus org-wide totals + the monthly budget —
{connections: [{connector_id, name, connector_type, provider, default_model, mtd_spend_usd, mtd_calls, policy, budget_state}], totals, org_monthly_budget_usd}.
HoneyframeClient.get_llm_policy()
get_llm_policy(connector_id: int) -> dict
The governance policy for one LLM connection (defaults + configured: false when unset).
HoneyframeClient.set_llm_policy()
set_llm_policy(connector_id: int, *, allowed_models: Optional[list] = None, monthly_budget_usd: Optional[float] = None, budget_blocking: bool = False, cache_enabled: bool = True, max_parallelism: Optional[int] = None, usable_by: str = 'all') -> dict
Upsert an LLM connection's governance policy. allowed_models=[]
(or None) = all models; monthly_budget_usd=None = no quota
(budget_blocking=False → warn-only, True → hard-stop over
budget); max_parallelism=None = unlimited; usable_by ∈ all |
admins. Needs org admin.
HoneyframeClient.llm_mesh_usage()
llm_mesh_usage(*, days: int = 30) -> dict
Windowed LLM spend roll-up for the org — per-connection, per-model,
and per-day ({days, by_connector, by_model, daily}). days is
clamped server-side to 1–365.
HoneyframeClient.list_meanings()
list_meanings() -> list[dict]
The org's semantic-type registry — platform built-ins ∪ the org's own
meanings, priority-ordered. Built-ins carry org_id: null and are
read-only.
HoneyframeClient.create_meaning()
create_meaning(name: str, label: Optional[str] = None, *, detector: str = 'pattern', name_pattern: Optional[str] = None, value_pattern: Optional[str] = None, values_list: Optional[list] = None, db_types: Optional[list] = None, mask_strategy: Optional[str] = None, sensitivity: Optional[str] = None, priority: Optional[int] = None) -> dict
Register a tenant meaning (e.g. customer_id with a name_pattern + a
value_pattern for conformance). detector ∈ pattern | values | type.
Returns the new meaning. Needs org admin; 409 on a duplicate name.
HoneyframeClient.update_meaning()
update_meaning(meaning_id: int, **fields) -> dict
Edit a tenant meaning (its name is immutable). 403 on a built-in.
HoneyframeClient.delete_meaning()
delete_meaning(meaning_id: int) -> dict
Deactivate a tenant meaning. 403 on a built-in.
HoneyframeClient.list_code_environments()
list_code_environments() -> list[dict]
The org's managed Python code environments.
Each row carries build_state — not_built | building | built | stale | failed — derived from the row AND the venv on disk, so it is
the field to branch on. status is the raw column and can say
ready for an env whose tree was wiped.
HoneyframeClient.code_environment_build_availability()
code_environment_build_availability() -> dict
{enabled, reason, sandbox_user} — whether this install can build
a code env at all, and what is missing when it cannot. Builds run under
the recipe sandbox, so the sandbox account is the precondition.
HoneyframeClient.get_code_environment()
get_code_environment(env_id: int) -> dict
One code environment. 404 when it is not this org's.
HoneyframeClient.create_code_environment()
create_code_environment(name: str, *, python_version: str = '3.11', packages: Optional[list] = None, description: Optional[str] = None, allow_source_builds: bool = False) -> dict
Declare a code environment (org admin).
packages are PEP 508 specs, optionally hash-pinned
(pandas==2.1.0 --hash=sha256:…); a malformed spec is rejected here,
not at build time. allow_source_builds turns OFF the default
wheels-only install — leave it False unless a package has no wheel.
HoneyframeClient.update_code_environment()
update_code_environment(env_id: int, **fields) -> dict
Edit a code environment (org admin). Editing the manifest of a BUILT
env leaves the venv in place and marks it stale until rebuilt.
HoneyframeClient.delete_code_environment()
delete_code_environment(env_id: int) -> dict
Delete a code environment and its materialized venv (org admin).
HoneyframeClient.validate_code_environment()
validate_code_environment(env_id: int) -> dict
PEP 508-parse every spec; returns {env, results, ok}. Installs
nothing.
HoneyframeClient.code_environment_build_log()
code_environment_build_log(env_id: int) -> dict
{status, build_state, stale, materialized, build_log, …} — the
poll surface while a build runs.
HoneyframeClient.build_code_environment()
build_code_environment(env_id: int, *, wait: bool = False, timeout: int = 1800, poll_interval: float = 3.0) -> dict
Materialize the environment as a real venv, under the recipe sandbox.
Returns the router's {env, started, materialized, message}
immediately. started=False means builds are unavailable on this
install and message says what is missing — it is NOT a failure to
raise on, and nothing was built.
wait=True polls /build-log until the build leaves building
and returns that final payload (build_state is built /
stale / failed); it raises TimeoutError if the build is
still running after timeout seconds — the build itself keeps going
server-side.
HoneyframeClient.list_assets()
list_assets(*, asset_type: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, scope: Optional[str] = None) -> list[dict]
List published assets, optionally filtered.
HoneyframeClient.get_asset()
get_asset(asset_id: int) -> PublishedAsset
HoneyframeClient.create_asset()
create_asset(asset_type: str, asset_key: str, title: str, *, description: str = '', config: Optional[dict] = None, theme: Optional[dict] = None, roles: Optional[list] = None, is_public: bool = False, icon: str = '', sort_order: int = 0) -> PublishedAsset
Create a published asset (dashboard|chat_agent|data_api|form|…).
HoneyframeClient.list_webapps()
list_webapps() -> list[dict]
List webapps in the current org (GET /api/webapps).
HoneyframeClient.get_webapp()
get_webapp(key: str) -> Webapp
Return a Webapp handle by asset_key (fetches its config).
HoneyframeClient.webapp_capabilities()
webapp_capabilities() -> dict
Discover, programmatically, what the webapp engine can build —
block kinds + their schemas, the sandbox/game contract, card types,
layout, and limits (GET /api/webapps/capabilities).
Read this instead of hardcoding assumptions: it tells you that a
sandboxed html block runs arbitrary canvas/WebGL JS (so you can build
games), the exact size/SQL limits, and what window.hf exposes inside
the iframe. The same self-description feeds the natural-language builder
(Webapp.ai_edit), so the engine and the AI agree on what's
possible.
caps = client.webapp_capabilities()
caps["block_kinds"] # card / code / html + examples
caps["block_kinds"][2]["sandbox"]["can"] # what a game block may do
caps["limits"]["max_html_block_chars"] # inline budget for a game
HoneyframeClient.publish_webapp()
publish_webapp(asset_key: str, title: str, *, config: Optional[dict] = None, description: str = '', theme: Optional[dict] = None, roles: Optional[list] = None, is_public: bool = False, icon: str = '', sort_order: int = 0, publish: bool = False) -> Webapp
Create a webapp asset and return its Webapp handle.
Webapps are project-scoped — the client must have project_id set
(it's sent as X-Project-Id), or the server rejects it. config
carries the page/nav/filter layout (card_ref blocks point at dashboard
cards; html/code blocks are inline).
⚠️ This creates a draft by default — the webapp viewer (/apps/<key>)
only serves published assets. Pass publish=True (or call
Webapp.publish) to make it live. See create_webapp for a
builder-friendly creator.
HoneyframeClient.create_webapp()
create_webapp(asset_key: str, title: str, *, pages: Optional[list] = None, nav: Optional[list] = None, filters: Optional[dict] = None, chrome: Optional[dict] = None, description: str = '', theme: Optional[dict] = None, roles: Optional[list] = None, is_public: bool = False, icon: str = '', publish: bool = False) -> Webapp
Create a webapp from page/nav builders in one call.
pages is a list from page (blocks from
card_ref / html_block /
code_card); nav from
nav_item. Set publish=True to make it live at
/apps/<asset_key> immediately. Idempotency is the caller's job —
use a fresh asset_key or Webapp.update to edit an existing one.
HoneyframeClient.get_api_service()
get_api_service(asset_id: int) -> APIService
Return an APIService handle (fetches its config).
HoneyframeClient.create_api_service()
create_api_service(asset_key: str, title: str, *, endpoints: Optional[list] = None, publish: bool = False, description: str = '', roles: Optional[list] = None, is_public: bool = False, icon: str = '', project_id: Optional[int] = None) -> APIService
Create a multi-endpoint API service and return its handle.
endpoints is a list from sql_endpoint /
lookup_endpoint / model_endpoint.
API services are project-scoped — the client must have project_id
set (or pass it), else the server rejects it. Creates a draft; pass
publish=True to make the endpoints callable immediately.
HoneyframeClient.list_agents()
list_agents() -> dict
Agent library ({pinned, enterprise, project, recent_conversations}).
HoneyframeClient.get_agent()
get_agent(agent_id: int) -> Agent
Return an Agent handle bound to a published agent id.
HoneyframeClient.chat()
chat(message: str, *, agent_id: Optional[int] = None, session_id: Optional[int] = None, model: Optional[str] = None, webapp_key: Optional[str] = None, page_key: Optional[str] = None) -> dict
Send a chat message (optionally to a specific agent_id).
webapp_key (with optional page_key) auto-grounds a SQL-mode
agent in that webapp's dashboard cards — the same embedded-assistant
grounding the webapp viewer applies, exposed for programmatic use.
HoneyframeClient.send_push()
send_push(title: str, body: str, *, user_ids: Optional[list] = None, role: Optional[str] = None, data: Optional[dict] = None) -> dict
Send a push notification to users by id and/or role (admin only).
Targets the registered mobile devices of the given users (and/or every
user with role) and returns {sent, pruned, total, users}. The
primitive behind proactive notifications — e.g. a scheduled director
briefing pushing role="director". Requires an admin/superadmin token.
HoneyframeClient.list_datasets()
list_datasets(**filters: Any) -> list[dict]
List datasets in the current project (requires project_id set).
HoneyframeClient.get_dataset()
get_dataset(name: str) -> Dataset
Return a Dataset handle in the current project.
HoneyframeClient.ai_search_datasets()
ai_search_datasets(intent: str, *, project_id: Optional[int] = None, tags: Optional[list] = None, limit: int = 10) -> dict
Rank datasets by relevance to a natural-language intent.
POST /api/datasets/ai-search — the same catalog-discovery ranking
the dashboard chat agent calls as a tool. project_id=None (the
default) searches across every project in the caller's org; pass a
project_id to confine it to one (the server 404s a project outside
your org). tags filters candidates before ranking; limit caps
the result list.
Returns {"results": [...], "intent": ..., "count": n}. Needs
project.edit; org admins see beyond the currently-pinned project.
HoneyframeClient.register_source_table()
register_source_table(schema_name: str, table_name: str, *, connector_id: Optional[int] = None, friendly_name: str = '', name: Optional[str] = None) -> Dataset
Register a raw table as a source_table dataset in the current project.
HoneyframeClient.register_schema()
register_schema(schema_name: str, *, connector_id: int, search: str = '') -> list[Dataset]
Register every table in a connector schema in the current project.
HoneyframeClient.sql()
sql(query: str, *, connector_id: Optional[int] = None, row_limit: int = 10000, params: Optional[dict] = None) -> Any
Run ad-hoc SQL in the current project and return a DataFrame.
The headline analyst path — one call from SQL to a DataFrame. Requires
project_id to be set on the client (pass it at construction or via
using). params are named binds (WHERE d >= :p_start
with params={"p_start": "2026-01-01"}). See
Project.sql for truncation.
Constants
| Name | Value |
|---|---|
DEFAULT_TIMEOUT | 60.0 |
PAT_DEFAULT_DAYS | 90 |
PAT_MAX_DAYS | 730 |
DEFAULT_MAX_RETRIES | 2 |
DEFAULT_RETRY_BACKOFF | 0.5 |
INSECURE_HTTP_ENV | 'HONEYFRAME_ALLOW_INSECURE_HTTP' |
Verified against honeyframeapi 0.1.8.