{"slug": "screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of", "title": "Screen Every Inbound Call at the Carrier Edge: A Fraud Firewall in 178 Lines of Python", "summary": "A developer built an Edge Fraud Firewall in 178 lines of Python that screens inbound calls at the carrier edge using Telnyx APIs and AI inference. The system classifies callers as CLEAN, SUSPICIOUS, or BLOCK, routing suspicious calls to a honeypot that wastes scammers' time.", "body_md": "*Originally published on lowlatencyclub.ai*\n\nEvery inbound call is a decision. Is this caller legitimate, or is it a scammer, robocaller, or toll-fraud bot? Most systems make that decision too late — after the call reaches the application layer, consuming resources and potentially connecting to a human agent who wastes 5 minutes on a fake call.\n\nThe Edge Fraud Firewall flips the order. It screens every inbound call at the carrier edge — before your app sees it — using three Telnyx APIs on a single platform: Number Lookup for caller identity, AI Inference for risk classification, and Call Control for reject/forward/route decisions.\n\nThe entire firewall is 178 lines of Python in a single Flask file.\n\nWhen a call hits a Telnyx number, the platform sends a `call.initiated`\n\nwebhook to the Flask server. Before doing anything else, the server verifies the Ed25519 webhook signature — if the request is not from Telnyx, it returns 401 and stops.\n\nFor verified webhooks, the screening pipeline runs in order:\n\n`CLEAN`\n\n, `SUSPICIOUS`\n\n, or `BLOCK`\n\n.`CLEAN`\n\n→ answer and forward to your real number`SUSPICIOUS`\n\n→ answer and route to a honeypot (endless hold loop)`BLOCK`\n\n→ reject and add to the blocklistThe system prompt is deliberately constrained — one word only:\n\n``` python\ndef classify_caller(phone, lookup_data):\n    try:\n        resp = requests.post(INFERENCE_URL, headers=HEADERS, timeout=15, json={\n            \"model\": AI_MODEL,\n            \"messages\": [\n                {\"role\": \"system\", \"content\": \"You are a fraud detection system. Analyze caller data and respond with ONLY one word: CLEAN, SUSPICIOUS, or BLOCK.\"},\n                {\"role\": \"user\", \"content\": f\"Caller: {phone}\\nCarrier: {lookup_data.get('carrier', {}).get('name', 'unknown')}\\nType: {lookup_data.get('carrier', {}).get('type', 'unknown')}\\nCountry: {lookup_data.get('country_code', 'unknown')}\"}\n            ]\n        })\n        if resp.ok:\n            return resp.json()[\"choices\"][0][\"message\"][\"content\"].strip().upper()\n    except Exception as e:\n        app.logger.error(\"Classification failed: %s\", e)\n    return \"CLEAN\"\n```\n\nOne-word output keeps inference latency to a single token and makes parsing trivial — no JSON, no regex, just a string comparison.\n\nIf the AI call fails for any reason, the function defaults to `CLEAN`\n\n. This is a safe-fail — if the screening service is unavailable, legitimate callers still get through.\n\nWhen the AI classifies a call as `SUSPICIOUS`\n\n, the firewall routes it to a honeypot instead of rejecting or forwarding. The honeypot answers the call and plays a hold message, then loops indefinitely:\n\n```\n# call.answered → honeypot flow\nif flow == \"honeypot\":\n    requests.post(f\".../calls/{call_control_id}/actions/speak\",\n                  json={\"payload\": \"Please hold while I connect you to a specialist.\",\n                        \"voice\": \"female\", \"language\": \"en-US\",\n                        \"client_state\": encode_state({\"flow\": \"honeypot_hold\"})})\n\n# call.speak.ended → loop forever\nif state.get(\"flow\") == \"honeypot_hold\":\n    time.sleep(2)\n    requests.post(f\".../calls/{call_control_id}/actions/speak\",\n                  json={\"payload\": \"All specialists are currently busy. Please continue to hold.\",\n                        \"client_state\": encode_state({\"flow\": \"honeypot_hold\"})})\n```\n\nThe scammer stays on the line, burning their time and resources.\n\nTelnyx Call Control is webhook-driven — each call action triggers a new webhook event. To track which flow a call is in (forward vs honeypot), the app uses `client_state`\n\n, a base64-encoded JSON blob that Telnyx passes back in the next webhook:\n\n``` python\ndef encode_state(data):\n    return base64.b64encode(json.dumps(data).encode()).decode()\n\ndef decode_state(b64):\n    try:\n        return json.loads(base64.b64decode(b64).decode())\n    except Exception:\n        return {}\n```\n\nNo external database needed — the state travels with the webhook.\n\nThe first thing the webhook handler does is verify the request is from Telnyx:\n\n```\ntry:\n    client.webhooks.unwrap(request.get_data(as_text=True), headers=dict(request.headers))\nexcept Exception:\n    return jsonify({\"error\": \"invalid signature\"}), 401\n```\n\nThe Telnyx Python SDK verifies the Ed25519 signature against the raw request body. If verification fails, the request is rejected before any processing happens.\n\n```\ngit clone https://github.com/team-telnyx/telnyx-code-examples.git\ncd telnyx-code-examples/edge-fraud-firewall-python\ncp .env.example .env\npip install -r requirements.txt\npython app.py\nngrok http 5000\n```\n\nConfigure the webhook URL in the [Telnyx Portal](https://portal.telnyx.com/call-control/applications) — set the Call Control Application webhook URL to `https://<your-ngrok-id>.ngrok.io/webhooks/voice`\n\n.\n\nFraud screening typically runs at the application layer — after the call is already connected. By that point, the fraud has already consumed SIP trunks, media servers, and agent time.\n\nScreening at the carrier edge means the decision happens on the same network that carries the call. Number Lookup and AI Inference run on Telnyx infrastructure, not a third-party API called over the public internet. The screen-then-route decision is fast enough to sit inline on every inbound call.\n\nThis sample uses in-memory state. For production:\n\n`gunicorn -w 4 app:app`\n\nas a process manager", "url": "https://wpnews.pro/news/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of", "canonical_source": "https://dev.to/harpreetseehra/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of-python-mi4", "published_at": "2026-07-23 11:01:26+00:00", "updated_at": "2026-07-23 11:31:57.074438+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-products", "developer-tools"], "entities": ["Telnyx", "Flask"], "alternates": {"html": "https://wpnews.pro/news/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of", "markdown": "https://wpnews.pro/news/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of.md", "text": "https://wpnews.pro/news/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of.txt", "jsonld": "https://wpnews.pro/news/screen-every-inbound-call-at-the-carrier-edge-a-fraud-firewall-in-178-lines-of.jsonld"}}