{"slug": "build-an-ai-outbound-call-campaign-with-python-and-telnyx", "title": "Build an AI Outbound Call Campaign with Python and Telnyx", "summary": "Telnyx has released an open-source AI Call Campaign Orchestrator built with Python, Flask, Telnyx Call Control, the Telnyx Agent SDK, SQLite, and SMS. The tool provides a backend template for outbound call campaigns, handling queueing, rate limiting, webhook verification, result tracking, and SMS summaries. It exposes a simple API for starting campaigns and polling status, with code available on GitHub.", "body_md": "Outbound call campaigns look simple until you need them to behave like real software.\n\nCalling one number is easy. Calling a list of numbers means you suddenly care about queueing, rate limits, call state, webhook verification, result tracking, and summaries for the team.\n\nI built a small example for that pattern: an AI Call Campaign Orchestrator using Python, Flask, Telnyx Call Control, the Telnyx Agent SDK, SQLite, and SMS.\n\nCode: [https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-call-campaign-orchestrator](https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-call-campaign-orchestrator)\n\nThe app exposes a simple API:\n\n`POST /campaign`\n\nstarts a campaign from a list of phone numbers`GET /campaign/<campaign_id>`\n\nreturns campaign status and call results`POST /webhooks/call`\n\nreceives Telnyx Call Control events`GET /health`\n\nconfirms the service is runningThe interesting part is what happens after you submit the campaign.\n\nThe `CampaignAgent`\n\nqueues the calls, applies a rate limit, places outbound calls through Call Control, stores results in SQLite, and sends an SMS summary when the campaign is complete.\n\n``` php\nPOST /campaign\n  -> queue calls\n  -> rate-limit delivery\n  -> place calls with Call Control\n  -> receive signed webhooks\n  -> store results in SQLite\n  -> send SMS summary\n```\n\nYou send a list of E.164 phone numbers to `POST /campaign`\n\n:\n\n```\ncurl -X POST http://localhost:5000/campaign \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"phone_numbers\": [\n      \"+15551234567\",\n      \"+15557654321\",\n      \"+15559876543\"\n    ]\n  }'\n```\n\nThe API returns a campaign ID:\n\n```\n{\n  \"campaign_id\": \"3f2c1a5e-8b7d-4e6f-9a0c-1d2e3f4a5b6c\",\n  \"status\": \"started\"\n}\n```\n\nFrom there, the agent owns the campaign lifecycle.\n\nOutbound communication workflows need pacing.\n\nIf you fire too many calls at once, you can create a bad user experience and run into carrier or operational limits. This sample uses `CALL_RATE_LIMIT_PER_MINUTE`\n\nso campaign delivery is controlled from configuration instead of buried inside the call loop.\n\nThat makes the campaign behavior easier to tune without rewriting the app.\n\nFor each queued number, the app places an outbound Call Control call with the Telnyx Python SDK.\n\nThe app needs:\n\n`TELNYX_API_KEY`\n\n`TELNYX_CONNECTION_ID`\n\n`TELNYX_PHONE_NUMBER`\n\n`TELNYX_WEBHOOK_URL`\n\nThe webhook URL points back to the app, so call lifecycle events can update campaign state as calls are answered, completed, or fail.\n\nThe webhook endpoint uses `telnyx.webhooks.unwrap()`\n\nwith the Telnyx Ed25519 public key.\n\nThat matters because webhook handlers should not blindly trust incoming HTTP requests. The app verifies that the event really came from Telnyx before it updates call state.\n\n``` php\nTelnyx Call Control event\n  -> POST /webhooks/call\n  -> verify signature\n  -> update campaign result\n```\n\nAt any point, you can poll:\n\n```\ncurl http://localhost:5000/campaign/<campaign_id>\n```\n\nThe response includes total calls, completion status, and per-number results.\n\nThat gives you a simple campaign dashboard API without adding another database service just for the sample.\n\nWhen the campaign finishes, the app sends a summary SMS using Telnyx Messaging.\n\nYou configure:\n\n`TELNYX_SMS_FROM`\n\n`TELNYX_SMS_TO`\n\nFor a demo, this is a clean way to prove the workflow completed. In a production version, the same step could also notify Slack, update a CRM, or send a report to another internal system.\n\nThe app is not trying to be a full campaign product.\n\nIt is showing the backend shape you need for one:\n\nThat is the useful part. It gives you the skeleton for a durable communications workflow without starting from a pile of disconnected services.\n\nClone the repo:\n\n```\ngit clone https://github.com/team-telnyx/telnyx-code-examples.git\ncd telnyx-code-examples/ai-call-campaign-orchestrator\n```\n\nCreate a virtual environment and install dependencies:\n\n```\npython3 -m venv venv\nsource venv/bin/activate\npip install -r requirements.txt\n```\n\nConfigure your environment:\n\n```\ncp .env.example .env\n```\n\nThen fill in your Telnyx API key, connection ID, phone number, webhook URL, public key, SMS settings, and call rate limit.\n\nRun the app:\n\n```\npython app.py\n```\n\nResources:", "url": "https://wpnews.pro/news/build-an-ai-outbound-call-campaign-with-python-and-telnyx", "canonical_source": "https://dev.to/sonam_50a41a4ced7e6b4f3fa/build-an-ai-outbound-call-campaign-with-python-and-telnyx-3hge", "published_at": "2026-08-26 21:58:10+00:00", "updated_at": "2026-08-26 22:48:14.982279+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-infrastructure"], "entities": ["Telnyx", "Python", "Flask", "SQLite", "GitHub"], "alternates": {"html": "https://wpnews.pro/news/build-an-ai-outbound-call-campaign-with-python-and-telnyx", "markdown": "https://wpnews.pro/news/build-an-ai-outbound-call-campaign-with-python-and-telnyx.md", "text": "https://wpnews.pro/news/build-an-ai-outbound-call-campaign-with-python-and-telnyx.txt", "jsonld": "https://wpnews.pro/news/build-an-ai-outbound-call-campaign-with-python-and-telnyx.jsonld"}}