Skip to main content

Telenow voice AI SDK for Python — place AI agent phone calls, mint browser/app call sessions, transfer & end live calls, verify webhooks, and stream your own LLM into calls (FastAPI/Django SSE helpers). Stdlib only.

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

telenow-0.1.2.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

telenow-0.1.2-py3-none-any.whl (9.8 kB view details)

Uploaded Python 3

File details

Details for the file telenow-0.1.2.tar.gz.

File metadata

  • Download URL: telenow-0.1.2.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for telenow-0.1.2.tar.gz
Algorithm Hash digest
SHA256 8377e750f7cae3dbde20ab0fd850401997373ab0baae2089f1e2d99c8cd26546
MD5 1adc990005359e92320ea93cf0e3f12a
BLAKE2b-256 10692acf53470eeb919d106b05993eee0d9f6b5e693583218327666cb43c53f1

See more details on using hashes here.

File details

Details for the file telenow-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: telenow-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 9.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for telenow-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 5c3ada8f0eefecce78c423846d0e4d8f2028d3912c4e6c21f5e41c78c2a92775
MD5 e4226a4c46d20d9ed3f5a2a5dab051ca
BLAKE2b-256 e527fdd795ff9e11166327009209a51445e8c249e1039abb076750b342105642

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page