Skip to main content

telenow (Python)

Telenow voice AI SDK for Python 3.8+ — stdlib only (no requests), fully typed (py.typed). From your backend you can: place AI agent phone calls, mint browser/app call sessions, transfer/end live calls, verify webhooks, manage agents, and build Custom API (bring-your-own-LLM) streaming endpoints for FastAPI, Django, or Flask.

pip install telenow            # core (zero dependencies)
pip install "telenow[django]"  # + the Django webhook decorator

Before you start

  • A Telenow account + agent (dashboard → Agents). Copy the agent ID from the agent page (or its Publish tab samples).
  • An org API key — dashboard → Developers tab. Keep it server-side only; it's sent as the X-API-Key header.
  • Phone calls additionally need a phone number attached to the agent (dashboard → Numbers).
import os
from telenow import Telenow

tn = Telenow(
    api_key=os.environ["TELENOW_API_KEY"],   # required
    base_url="https://api.telenow.ai",        # default — override for self-hosted
)

Phone calls

result = tn.create_call(
    "AGENT_UUID",
    "+15551234567",                                   # E.164
    variables={"order_id": "A-1042"},                 # context variables (required ones must be present)
    identifier="customer-9",                          # trusted caller identity for the agent's tools
    first_response="Hi! Calling about your delivery.",# optional opener override for THIS call
    machine_detection="true",                         # "true" = auto-voicemail, "hangup" (Plivo)
)
session_id = result["sessionId"]

Control a live call (phone or web — the client SDKs expose call.sessionId for exactly this):

tn.transfer_call(session_id, "+15557654321")   # warm transfer to a human
tn.end_call(session_id)                        # hang up

Web calls (mint a session for your frontend)

The recommended browser/app flow: mint here, hand the result to the client, the client SDK connects — the API key never reaches the browser.

@app.post("/voice/session")                    # FastAPI shown; any framework works
async def voice_session():
    return tn.init_web_call(
        "AGENT_UUID",
        variables={"customer_name": "Asha"},   # baked in server-side — client can't tamper
        identifier="customer-9",
    )
    # → {"sessionId": ..., "websocketUrl": ...}  → TelenowCall({ session })

Webhooks

Telenow signs every delivery with X-VoiceAI-Signature: sha256=<hex> (HMAC-SHA256 of the raw body). Always verify before trusting the payload.

Django (decorator verifies + parses for you):

from telenow.django import telenow_webhook

@telenow_webhook(secret=settings.TELENOW_WEBHOOK_SECRET)
def hook(request, event):                  # signature verified, body parsed
    if event["event"] == "call.ended":     # also: call.started, transcript.ready, tool.invoked
        ...
    return HttpResponse(status=200)

Anything else (FastAPI shown) — verify against the raw bytes:

from telenow import verify_webhook

@app.post("/webhooks/telenow")
async def hook(request: Request):
    raw = await request.body()
    if not verify_webhook(raw, request.headers.get("x-voiceai-signature", ""), SECRET):
        raise HTTPException(401)
    event = json.loads(raw)
    ...

Configure endpoints + events in the dashboard (Webhooks), per agent or org-wide. Payload shapes: webhook events reference.

Custom API — stream your own LLM into calls

When an agent's Brain is set to Custom API, Telenow runs STT + TTS and POSTs each user turn to your endpoint (?calling=true&stream=true, JSON body {"query": ..., "userId": ..., **payload}), then speaks your Server-Sent-Events reply as tokens arrive. telenow.custom_api emits the exact wire format.

FastAPI:

from telenow import custom_api
from fastapi.responses import StreamingResponse

@app.post("/telenow-llm")
async def llm(request: Request):
    body = await request.json()

    async def gen():
        async for token in my_llm_stream(body["query"]):
            yield token                          # str → spoken as it streams
        # yield custom_api.call_end("Goodbye!")  # dict → control event (hangs up after reply)

    return StreamingResponse(
        custom_api.sse_astream(gen()),
        media_type=custom_api.MEDIA_TYPE,
        headers=custom_api.SSE_HEADERS,          # disables proxy buffering (X-Accel-Buffering: no)
    )

Django / Flask (sync generators) — wrap with custom_api.sse_stream(gen()) in a StreamingHttpResponse / Response with the same media type + headers.

Notes that save debugging time:

  • Yield str for spoken token deltas; yield dict (e.g. custom_api.call_end()) for control events. [DONE] is appended for you — even if your generator raises midway, so the turn ends cleanly.
  • Without SSE_HEADERS, nginx buffers your stream and the agent goes silent, then speaks everything at once.
  • Transfer is a REST action, not an SSE event: call tn.transfer_call(session_id, to) from inside your handler.

Agents & everything else

tn.list_agents() / get_agent(id) / create_agent(data) / update_agent(id, data) mirror the Agents API. Anything not wrapped: call the REST API with the same X-API-Key header.

Errors

Every non-2xx (and {"success": false} envelope) raises TelenowError with .status and .body:

from telenow import TelenowError

try:
    tn.create_call("AGENT_UUID", "+15551234567")
except TelenowError as e:
    print(e.status, e, e.body)
Status Usual cause
401 / 403 Wrong/revoked API key, or the agent's API access toggle is off (Publish tab).
400 Missing required field — often a required context variable, or a non-E.164 number.
404 Wrong agent_id / session_id, or the session already ended.

Successful responses are unwrapped from the {"success", "data"} envelope — you get the data dict directly.

Test: python -m unittest discover tests.


What is Telenow?

Telenow is a voice AI platform for building production-grade phone and web agents. Pick a brain from the built-in LLM/STT/TTS providers (or bring your own model and carrier), give the agent a prompt, tools, and knowledge, and put it on a phone number, your website, or your app. Every call comes with recordings, transcripts, analytics, warm transfer to humans, outbound campaigns, and webhooks.

Release files for telenow 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for telenow 0.1.2
File Size Uploaded
telenow-0.1.2.tar.gz 9.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for telenow 0.1.2
File Interpreter ABI Platform
telenow-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 19.4 kB

Release files / telenow-0.1.2.tar.gz

Download URL telenow-0.1.2.tar.gz
Size 9.6 kB
Tags Source
SHA-256 checksum
How to use checksums
8377e750f7cae3dbde20ab0fd850401997373ab0baae2089f1e2d99c8cd26546
BLAKE2b-256 checksum
How to use checksums
10692acf53470eeb919d106b05993eee0d9f6b5e693583218327666cb43c53f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / telenow-0.1.2-py3-none-any.whl

Download URL telenow-0.1.2-py3-none-any.whl
Size 9.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c3ada8f0eefecce78c423846d0e4d8f2028d3912c4e6c21f5e41c78c2a92775
BLAKE2b-256 checksum
How to use checksums
e527fdd795ff9e11166327009209a51445e8c249e1039abb076750b342105642
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page