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 SDK backend client for Python / Django / FastAPI. Stdlib only (no requests).
pip install telenow # core
pip install "telenow[django]" # + Django helpers
from telenow import Telenow
tn = Telenow(api_key="...") # keep server-side
tn.create_call(agent_id="...", to="+15551234567", # outbound PSTN
first_response="Hi! Calling about your order.")
tn.transfer_call(session_id, to="+15557654321") # warm transfer
tn.end_call(session_id) # hang up
# Browser/app calls WITHOUT shipping a credential to the client:
# mint the session here, hand it to your frontend, the client SDK connects.
sess = tn.init_web_call(agent_id="...", variables={"customer_id": "123"})
# → {"sessionId": ..., "websocketUrl": ...} → client SDK `session` option
# Or mint a short-lived client token (requires the client-token backend phase):
tok = tn.create_client_token(agent_id="...", ttl_seconds=600,
variables={"customer_id": "123"})
# Verify a webhook (pass the RAW body bytes):
ok = tn.verify_webhook(request_body, signature_header, secret)
Custom API (bring your own LLM/workflow)
When an agent's Brain is "Custom API", Telenow POSTs each user turn to your
endpoint and speaks your streamed reply. telenow.custom_api produces the
exact SSE wire format:
from telenow import custom_api
from fastapi.responses import StreamingResponse
@app.post("/telenow-llm")
async def llm(request: Request):
body = await request.json() # {"query": ..., "userId": ..., **payload}
async def gen():
async for token in my_llm_stream(body["query"]):
yield token # spoken as it streams
# yield custom_api.call_end("Goodbye!") # optional hangup
return StreamingResponse(custom_api.sse_astream(gen()),
media_type=custom_api.MEDIA_TYPE,
headers=custom_api.SSE_HEADERS)
Django: wrap a sync generator with custom_api.sse_stream(...) in a
StreamingHttpResponse. To transfer the caller, call
tn.transfer_call(session_id, to=...) from your handler (transfer is a REST
action, not an SSE event).
Django webhooks:
from telenow.django import telenow_webhook
@telenow_webhook(secret=settings.TELENOW_WEBHOOK_SECRET)
def handle(request, event): # signature already verified
if event["event"] == "call.ended":
...
return HttpResponse(status=200)
Test: python -m unittest discover tests. Publish: see ../RELEASING.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file telenow-0.1.0.tar.gz.
File metadata
- Download URL: telenow-0.1.0.tar.gz
- Upload date:
- Size: 7.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fc0664860d3a1108be3f37183fe25900ba7bad61265b300b740342cd1e8ba282
|
|
| MD5 |
8b0a431484fa966909f31dd059407cd4
|
|
| BLAKE2b-256 |
54f6959fa13fa1eb36f9d824d6e80e1f6df7d8d1bd416e1a298cbea7f2b6b592
|
File details
Details for the file telenow-0.1.0-py3-none-any.whl.
File metadata
- Download URL: telenow-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b95b6a783b3142493c16e4448911ac3bd6434f3a2fba0f8531e2b52d5c66867b
|
|
| MD5 |
0f9ae4fffe7939051532ee7157eb3606
|
|
| BLAKE2b-256 |
bb1397e55a5efff345a0a44c3954997df0a3ffa352bfcfc3d19978ca5e8c6010
|