SDK Reference
Client libraries for Python (server & worker) and JavaScript/React (browser).
Installation
pip install hostdesk-sdkFor voice worker support (LiveKit agent), install with the gateway extra:
pip install hostdesk-sdk[gateway]Client
The Client is your main entry point. It provides access to calls, assistants, TTS, STT, and models.
from hostdesk import Client
client = Client(api_key="ek_...")
# Or set ECHOAI_API_KEY env var
client = Client()Constructor
| Parameter | Type | Description |
|---|---|---|
| api_key | str | None | API key. Falls back to ECHOAI_API_KEY env var. |
| base_url | str | None | API base URL. Default: https://api.hostdeskai.com |
| sandbox | bool | Use sandbox environment. Default: False |
Properties
client.calls — CallsAPI for outbound calls and call history
client.assistants — AssistantsAPI for CRUD assistant configs
client.tts — TTSAPI for text-to-speech generation
client.stt — STTAPI for speech-to-text transcription
client.models — ModelsAPI for listing available models
Calls
Place outbound calls and retrieve call history.
# Place an outbound call
result = client.calls.create(
phone_number="+14155551234",
objective="Confirm appointment for Friday at 3 PM",
assistant_id="asst_abc123", # optional
)
print(result.room_name) # "hostdesk-out-a1b2c3d4"
# List recent calls
calls = client.calls.list(limit=10, status="completed")
# Get a single call
call = client.calls.get("call_id_or_room_name")
# Get conversation history
messages = client.calls.messages("call_id_or_room_name")Assistants
Create and manage assistant configurations (system prompt, voice, model).
# Create an assistant
assistant = client.assistants.create(
name="Sales Agent",
system_prompt="You are a helpful sales agent...",
voice_id="a0e99841-438c-4a64-b679-ae501e7d6091",
llm_model="gemini-2.5-flash",
)
# List all assistants
assistants = client.assistants.list()
# Update
client.assistants.update(assistant.id, name="Senior Sales Agent")
# Delete
client.assistants.delete(assistant.id)Voice Worker
EchoWorker runs a voice agent that handles calls. It connects to LiveKit and processes audio in real time.
from hostdesk import EchoWorker
worker = EchoWorker(api_key="ek_...")
@worker.on_call
async def handle_call(call):
print(f"Call from {call.from_number}")
# Speak immediately
await call.say("Hello! How can I help you today?")
# Transfer to another number
await call.transfer("+14155559876", announce="Connecting you now")
# Hold / resume
call.hold()
call.resume()
# Access raw LiveKit room
room = call.livekit_room
worker.run()Token Mode
Workers can run without a LiveKit API key. They poll the HostDesk API for room tokens and join with those credentials. Set only ECHOAI_API_KEY — no LIVEKIT_API_KEY needed on the client.
join_room_with_token()
Lower-level function to join a specific LiveKit room with a pre-generated token.
from hostdesk import join_room_with_token
await join_room_with_token(
url="wss://my-project.livekit.cloud",
token="eyJhbG...",
on_call=handle_call,
)Webhooks
Verify incoming webhook signatures (HMAC-SHA256).
from hostdesk import verify_webhook
is_valid = verify_webhook(
payload=request_body,
# NOTE: the wire header names stay X-EchoAI-* — that's what the platform sends.
signature=headers["X-EchoAI-Signature"],
secret="whsec_...",
timestamp=int(headers["X-EchoAI-Timestamp"]),
)Function Calling
Register server-side functions that the voice agent can invoke via webhooks.
from hostdesk import FunctionHandler, create_function_webhook_app
handler = FunctionHandler(secret="whsec_...")
@handler.on("bookAppointment")
async def book_appointment(date: str, time: str, name: str):
# Your booking logic here
return {"confirmed": True, "date": date, "time": time}
@handler.on("lookupOrder")
async def lookup_order(order_id: str):
return {"status": "shipped", "tracking": "1Z999AA10123456784"}
# Mount as a Starlette/FastAPI app
app = create_function_webhook_app(handler, path="/webhook")
# Or handle manually in an existing route
result = await handler.handle_request(request)Error Handling
from hostdesk import (
HostDeskError, # base error
AuthError, # 401/403 — invalid API key
ValidationError, # 400/422 — bad request params
NotFoundError, # 404 — resource not found
RateLimitError, # 429 — too many requests
ProviderError, # 502/503 — upstream provider error
)
try:
client.calls.create(phone_number="+1...")
except AuthError:
print("Check your API key")
except RateLimitError as e:
print(f"Slow down: {e}")
except HostDeskError as e:
print(f"API error: {e}")