{"id":37067917,"url":"https://github.com/frejun-tech/teler-py","last_synced_at":"2026-01-14T07:58:59.188Z","repository":{"id":305123353,"uuid":"1003089210","full_name":"frejun-tech/teler-py","owner":"frejun-tech","description":"This library offers a lightweight and developer-friendly abstraction over the FreJun Teler API.","archived":false,"fork":false,"pushed_at":"2025-07-18T11:20:15.000Z","size":37,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-28T03:00:03.184Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frejun-tech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-16T15:52:08.000Z","updated_at":"2025-10-22T13:11:30.000Z","dependencies_parsed_at":"2025-07-18T13:32:01.820Z","dependency_job_id":"c3acb011-cb48-4da9-8c58-17081d9058ba","html_url":"https://github.com/frejun-tech/teler-py","commit_stats":null,"previous_names":["frejun-tech/teler-py"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/frejun-tech/teler-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frejun-tech%2Fteler-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frejun-tech%2Fteler-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frejun-tech%2Fteler-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frejun-tech%2Fteler-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frejun-tech","download_url":"https://codeload.github.com/frejun-tech/teler-py/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frejun-tech%2Fteler-py/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T07:58:58.557Z","updated_at":"2026-01-14T07:58:59.180Z","avatar_url":"https://github.com/frejun-tech.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Teler \n\nThis library offers a lightweight and developer-friendly abstraction over the FreJun Teler API.\n\n## Basic Usage\n\nThe built-in client interfaces provide methods for creating and managing Teler's REST resources.\n\n### Client (Synchronous)\n\n```python\nfrom teler import Client\n\nTELER_API_KEY = 'API_KEY'\nclient = Client(TELER_API_KEY)\n\ncall = client.calls.create(\n    from_number=\"+123*******\",\n    to_number=\"+456*******\",\n    flow_url=\"https://example.com/flow\",\n    status_callback_url=\"https://example.com/status\",\n    record=True,\n)\n```\n\n### AsyncClient (Asynchronous)\n\n```python\nfrom teler import AsyncClient\n\nTELER_API_KEY = 'API_KEY'\nclient = AsyncClient(TELER_API_KEY)\n\nasync def initiate_call()\n    call = await client.calls.create(\n        from_number=\"+123*******\",\n        to_number=\"+456*******\",\n        flow_url=\"https://example.com/flow\",\n        status_callback_url=\"https://example.com/status\",\n        record=True,\n    )\n\nasyncio.run(initiate_call())\n```\n\n## Media Streaming\n\nThe library provides a simple interface for integrating real-time call audio streams from Teler into your application, unlocking advanced capabilities such as Conversational AI, Real-time transcription, and Actionable insights.\n\n### `StreamConnector`\n\nThis class lets you bridge the call audio stream to your desired websocket endpoint. It handles message relaying between the two streams via pluggable handlers, making it highly customizable.\nIt also handles graceful shutdown of the media streams in case of any unexpected errors.\n\nIt takes the following 4 parameters:\n\n1. **stream_type** - Only `StreamType.BIDIRECTIONAL` is supported for now.\n2. **remote_url** - The remote websocket URL where the call audio stream needs to be bridged.\n3. **call_stream_handler** - A `StreamHandler` coroutine that handles the call audio stream.\n4. **remote_stream_handler** - A `StreamHandler` coroutine that handles the remote audio stream.\n\n### `StreamHandler`\n\nA `StreamHandler` coroutine receives the incoming messages on the websocket, processes them and returns a tuple of `(str, StreamOp)` where `StreamOp` is an operation flag that decides the subsequent action the `StreamConnector` will take.\n\n`StreamOp` can be one of:\n\n1. **StreamOp.RELAY** - Relays the message to the other stream. The message needs to be supplied as a string as the first item in the returned tuple.\n2. **StreamOp.PASS** - Does not relay any message to the other stream. Any message in the returned tuple will be ignored.\n3. **StreamOp.STOP** - Stops both streams, ends the call and exits gracefully. Any message in the returned tuple will be ignored.   \n\n## Sample Application - Implementing AI-driven outbound calling using Teler and Elevenlabs\n\nThe following application utilizes the Teler SDK to start a call and bridge its audio stream to an ElevenLabs AI agent that responds in real time. The response is then streamed back to Teler and played over the call.\n\n\n```python\nimport json\nimport logging\n\nfrom fastapi import APIRouter, WebSocket, WebSocketDisconnect, Body, status, HTTPException\nfrom fastapi.responses import JSONResponse\nfrom pydantic import BaseModel, HttpUrl\nfrom typing import Annotated\n\nfrom teler.streams import StreamConnector, StreamOp, StreamType\nfrom teler import AsyncClient, CallFlow\n\nrouter = APIRouter()\nlogger = logging.getLogger(__name__)\n\n# Global variables\nELEVENLABS_AGENT_ID = \"agent_*****\"\nELEVENLABS_WEBSOCKET_URL = f\"wss://api.elevenlabs.io/v1/convai/conversation?agent_id={ELEVENLABS_AGENT_ID}\"\n\nTELER_API_KEY = \"TELER_API_KEY\"\nBACKEND_DOMAIN = \"example.com\"\nFROM_NUMBER = \"+91123*******\"\nTO_NUMBER = \"+91456*******\"\n\nclass CallFlowRequest(BaseModel):\n    call_id: str\n    account_id: str\n    from_number: str\n    to_number: str\n\nasync def call_stream_handler(message: str):\n    msg = json.loads(message)\n    if msg[\"type\"] == \"audio\":\n        payload = json.dumps({\"user_audio_chunk\": msg[\"data\"][\"audio_b64\"]})\n        return (payload, StreamOp.RELAY)\n    return ({}, StreamOp.PASS)\n\ndef remote_stream_handler():\n    chunk_id = 1\n\n    async def handler(message: str):\n        nonlocal chunk_id\n        msg = json.loads(message)\n        if msg[\"type\"] == \"audio\":\n            payload = json.dumps(\n                {\n                    \"type\": \"audio\",\n                    \"audio_b64\": msg[\"audio_event\"][\"audio_base_64\"],\n                    \"chunk_id\": chunk_id,\n                }\n            )\n            chunk_id += 1\n            return (payload, StreamOp.RELAY)\n        elif msg[\"type\"] == \"interruption\":\n            payload = json.dumps({\"type\": \"clear\"})\n            return (payload, StreamOp.RELAY)\n        return ({}, StreamOp.PASS)\n\n    return handler\n\nconnector = StreamConnector(\n    stream_type=StreamType.BIDIRECTIONAL,\n    remote_url=ELEVENLABS_WEBSOCKET_URL,\n    call_stream_handler=call_stream_handler,\n    remote_stream_handler=remote_stream_handler(),\n)\n\n@router.post(\"/flow\", status_code=status.HTTP_200_OK, include_in_schema=False)\nasync def stream_flow(payload: CallFlowRequest):\n    \"\"\"\n    Build and return Stream flow.\n    \"\"\"\n    stream_flow = CallFlow.stream(\n        ws_url=f\"wss://{BACKEND_DOMAIN}/media-stream\",\n        chunk_size=500,\n        record=True\n    )\n    return JSONResponse(stream_flow)\n\n@router.post(\"/webhook\", status_code=status.HTTP_200_OK, include_in_schema=False)\nasync def webhook_receiver(data: Annotated[dict, Body()]):\n    logger.info(f\"--------Webhook Payload-------- {data}\")\n    return JSONResponse(content=\"Webhook received.\")\n\n@router.get(\"/initiate-call\", status_code=status.HTTP_200_OK)\nasync def initiate_call():\n    \"\"\"\n    Initiate a call using Teler SDK.\n    \"\"\"\n    try:\n        async with AsyncClient(api_key=TELER_API_KEY, timeout=10) as client:\n            call = await client.calls.create(\n                from_number=f\"{FROM_NUMBER}\",\n                to_number=f\"{TO_NUMBER}\",\n                flow_url=f\"https://{BACKEND_DOMAIN}/flow\",\n                status_callback_url=f\"https://{BACKEND_DOMAIN}/webhook\",\n                record=True,\n            )\n            logger.info(f\"Call created: {call}\")\n        return JSONResponse(content={\"success\": True})\n    except Exception as e:\n        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=\"Failed to create call.\")\n\n@router.websocket(\"/media-stream\")\nasync def handle_media_stream(websocket: WebSocket):\n    await websocket.accept()\n    logger.info(\"WebSocket connected.\")\n    await connector.bridge_stream(websocket)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrejun-tech%2Fteler-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrejun-tech%2Fteler-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrejun-tech%2Fteler-py/lists"}