API reference

Bots

Create and manage your agents - their prompt, model, voice settings, and call controls - over the HTTP API. Read endpoints need bots:read; create/update/delete need bots:write.

Endpoints

Method & pathAbilityNotes
GET /api/v1/botsbots:readList bots (no pagination; ?metadata.<key>=<value> filters)
POST /api/v1/botsbots:writeCreate → returns { id }
GET /api/v1/bots/{id}bots:readFull bot object
PUT /api/v1/bots/{id}bots:writePartial update → message only
DELETE /api/v1/bots/{id}bots:writeSoft-delete (status → inactive)
POST /api/v1/bots/discoverbots:writeAI draft (SSE; JSON with Accept: application/json) - does not persist
PATCH /api/v1/bots/{id}/metadatabots:writeRaw metadata object (string values, ≤ 8 KB)

The bot object

Fields returned by GET /api/v1/bots/{id}:

FieldTypeNotes
id, tenant_iduuid
name, descriptionstring
system_promptstringThe assembled instructions.
prompt_builder, settingsstringJSON-encoded strings (parse client-side).
statusstringactive | inactive
bot_typestringchatbot (an Agent) | agent (an Autonomous Agent)
schedule, next_run_at, last_run_atstringAgent scheduling.
agent_goal, output_config, max_iterations, timeout_secondsmixedAgent-mode controls.
metadataobjectYour own key/value data.
created_at, updated_atstringRFC 3339.
The console's conversation_count / tool_count are dashboard-computed and are not part of the v1 bot object.

List bots

GET /api/v1/bots returns all your bots. There's no pagination; narrow the set with metadata filters, e.g. ?metadata.team=support.

curl https://app.hania.ai/api/v1/bots \
  -H "Authorization: Bearer $HANIA_API_KEY"

Create a bot

POST /api/v1/bots creates a bot and returns { "id": "…" }. Provide a name and either a system_prompt or a prompt_builder to assemble one from. Creation is plan-capped: it returns 402 if the workspace's bot limit is reached, and 502 if the voice provider (Cartesia) sync fails. Common body fields:

FieldNotes
nameRequired.
system_promptRequired unless assembled from prompt_builder.
model, temperatureLLM model id and sampling.
chat_greetingOpener for chat conversations.
tts_provider, tts_voice, voice_greetingVoice output (tts_provider ∈ cartesia | deepgram).
end_call_enabled, call_transfer_enabled, call_transfer_numberIn-call controls. call_transfer_number is an E.164 number or a SIP URI, and is required when call_transfer_enabled is true. It isn't stored while transfer is off: saving with call_transfer_enabled false removes it. See In-call controls.
outbound_calls_enabled, max_call_secondsOutbound voice controls.
prompt_builder.call_featuresThe prompt half of the call controls: end_call_enabled, call_transfer_enabled, outbound_calls_enabled. Set each to the same value as the matching top-level field, so the agent has both the tool and the instructions for using it.
enable_agent_tracing, enable_confidence_scoring, enable_response_validationPer-bot response-quality flags (booleans, off by default). See Response quality.
bot_type, status, metadataType, state, and your own data.
On update (PUT), nullable fields follow an "omit to leave unchanged" rule - send only what you want to change. The three response-quality flags are the exception; see below.

Response quality

Three optional booleans switch on per-bot quality checks. They sit alongside model and temperature in the bot body, and come back inside the bot's settings object on GET (an absent key means off). All three are off by default and opt-in per bot.

FieldWhat it does
enable_confidence_scoringGrades each reply with an extra LLM call before it's sent, and replaces a low-confidence answer with a safe "I don't have enough reliable information" message. The grade runs on the bot's own model, so it adds latency (around 700 ms) and cost on the critical path before every reply. The refusal threshold is fixed at 0.3 and isn't configurable.
enable_response_validationA passive, background hallucination check that runs only when the turn used sources (knowledge or tool results). It adds no user-facing latency and never changes or blocks the answer; findings go to logs and traces.
enable_agent_tracingRecords per-step execution traces for the trace view and analytics. Observability only; it doesn't affect replies and adds no AI cost.
These flags are stored only when set, so an omitted key is read as off and any stored value is dropped - the opposite of the "omit to leave unchanged" rule. Send an explicit true or false for all three on every save, or a toggle set earlier will be cleared.

Completion check

For an Autonomous Agent (bot_type="agent"), two settings control the completion check on its runs. They go in the bot body on create and update, and come back inside settings on GET.

FieldWhat it does
goal_check_enabledBoolean. false turns the check off, so a run ends on the agent's reply. Absent means on.
goal_check_modelA model id to run the check on. Empty or absent uses the agent's own model.
A save without goal_check_enabled turns the check back on, so send false on every save for an agent that should run without it.

Hania Code

These fields give an agent Hania Code and control it. Like the quality flags, they go in the bot body on create and update, and come back inside the bot's settings object on GET. What each one does, and how rules and hooks match, is explained in Hania Code settings.

FieldTypeWhat it does
code_enabledbooleanGives the agent Hania Code. Missing means off.
code_permission_modestringHow much runs without asking: manual (the default), accept_edits, plan, or auto. An unknown value returns 400 with field code_permission_mode.
code_auto_modelstringThe model auto mode's safety check runs on. Empty means the agent's own model.
code_permissionsarray of {permission, pattern, action}Rules applied after the built-in defaults; the last matching rule wins. action is allow, ask, or deny.
code_hooksobject{"PreToolUse": [...], "PostToolUse": [...]}, each item {matcher, command, timeout}. Commands that run before or after each change, on the computer the conversation is working on.
  • Saves replace the whole set of settings, so with Hania Code on, send code_enabled and code_permission_mode on every save, along with the safety-check model, rules and hooks you want kept. A save that leaves them out switches Hania Code off, or clears that setting.
  • When code_enabled is false or missing, the others are dropped on save.
  • code_auto_approve was removed on 2026-09-20. An agent that had it on now has code_permission_mode set to auto. Sending the old field does nothing.
  • An empty code_permissions or code_hooks isn't stored, which is the same as leaving it out. Don't send an event with an empty list, such as {"PreToolUse": []}; that is stored as written and does nothing. Send {} or leave the key out.
  • While Hania Code is on, an invalid mode, rule, or hook is refused with 400, code VALIDATION_FAILED, and field set to code_permission_mode, code_permissions, or code_hooks. The error names the rule or hook and what's wrong with it.

When confidence scoring or response validation is on, each graded turn's outcome (the score, whether the answer was refused, the validation verdict, and any unsupported claims) is available to operators in the console's per-bot Quality tab. It's an operator-only review view, scoped to your workspace; see Reviewing graded turns. Scores and verdicts are never shown to end customers.

Draft a bot with AI

POST /api/v1/bots/discover generates a draft bot configuration from a short description (and optional sources). It streams as Server-Sent Events by default, or returns JSON if you send Accept: application/json. The draft is returned, not saved - review it, then create the bot with POST /api/v1/bots. It returns 503 if no LLM is configured, or 502 on an upstream LLM failure.

Metadata

PATCH /api/v1/bots/{id}/metadata sets the bot's metadata object. Values are strings; the object must be ≤ 8 KB. Use it to attach your own identifiers, then filter lists with ?metadata.<key>=<value>.

Post-call hooks

Hooks run a configured tool after a call ends. They're gated by the same bots:read / bots:write abilities.

Method & pathAbility
GET /api/v1/bots/{botID}/post-call-hooksbots:read
POST /api/v1/bots/{botID}/post-call-hooksbots:write → { id }
PUT /api/v1/bots/{botID}/post-call-hooks/{hookID}bots:write
DELETE /api/v1/bots/{botID}/post-call-hooks/{hookID}bots:write

Hook object: id, bot_id, tool_configuration_id, tool_type, tool_name, run_order, enabled, params_template (object), created_at, updated_at. To create one, send tool_configuration_id (required), plus optional run_order, enabled (default true), and params_template. A hook is unique per (bot, tool configuration).