Every communications workflow has a question it needs answered before the first message or call goes out: what kind of number is this? Is it a mobile phone, a landline, or a VoIP line? Which carrier owns it? Has it been ported? The answers determine whether you send an SMS or place a voice call, whether you trust an inbound caller or flag them for review, and whether a lead's contact info is real or stale.
The Telnyx Number Lookup API returns carrier, line type, and portability data for any phone number in a single request. This walkthrough builds a Python Flask service that wraps that API with a 24-hour in-memory cache so repeat lookups are free and fast.
The canonical code example is in the Telnyx code examples repo:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/phone-number-lookup-python
What This Example Builds
The Flask app exposes three endpoints:
| Method | Path | Purpose |
|---|---|---|
POST |
/lookup |
Look up a number from a JSON body |
GET |
/lookup/<phone_number> |
Look up a number from the URL path |
GET |
/cache/stats |
Inspect the in-memory cache |
When a lookup request arrives, the app checks the cache first. On a cache miss, it calls the Telnyx Number Lookup API, extracts carrier name, carrier type, line type, number type, and portability status, caches the result for 24 hours, and returns a clean JSON response. Cached responses include "from_cache": true so the caller knows the data was served locally.
Why Phone Number Lookup Matters
Number lookup is not a standalone product — it is a building block. Developers use it to:
- Screen inbound calls — Check carrier and line type before connecting a caller to an agent. VoIP numbers from unknown carriers may warrant additional verification.
- Enrich leads — Sales teams want to know whether a prospect's number is a real mobile line or a disposable VoIP number before spending time on outreach.
- Route messages — Some messaging workflows behave differently for landlines (which cannot receive SMS) versus mobile numbers.
- Detect porting — A number that was recently ported may indicate a customer switching carriers, which matters for compliance and deliverability.
The Telnyx Number Lookup API provides this data from Telnyx's own carrier network — not resold from a third party.
Products Used
telnyx_products: [Number Lookup]
Number Lookup is a single API call: GET /v2/number_lookup/{phone_number}. No webhooks, no long-running jobs, no polling.
Architecture
HTTP Request (POST /lookup or GET /lookup/<number>)
|
v
+--------------------+ hit
| In-memory cache |-----------> cached result (from_cache: true)
| (24h TTL) |
+--------+-----------+
| miss
v
+--------------------+
| Telnyx Number |
| Lookup API |
+--------+-----------+
|
+---> carrier + line type + portability (cached, returned)
Prerequisites
- Python 3.8+
- A Telnyx account with a funded balance
- A Telnyx API key from the Telnyx Portal
- curl or Postman to test the endpoints
Setup
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/phone-number-lookup-python
cp .env.example .env
pip install -r requirements.txt
Edit .env and set your API key:
TELNYX_API_KEY=KEY0123456789ABCDEF
FLASK_DEBUG=false
Start the server:
python app.py
The app runs on http://localhost:5000.
How The Code Works
Client Initialization
The Telnyx Python SDK client is created once at startup:
client = telnyx.Telnyx(api_key=os.getenv("TELNYX_API_KEY"))
The Lookup Function
The core function validates the phone number format, checks the cache, and calls the Telnyx API on a miss:
def lookup_phone_number(phone_number: str) -> dict:
if not phone_number.startswith("+"):
raise ValueError("Phone number must be in E.164 format (e.g., +15551234567)")
cached_result = get_cached_lookup(phone_number)
if cached_result:
cached_result["from_cache"] = True
return cached_result
response = client.number_lookup.retrieve(phone_number)
lookup_data = {
"phone_number": response.data.phone_number,
"country_code": response.data.country_code,
"carrier": {
"name": response.data.carrier.name if response.data.carrier else None,
"type": response.data.carrier.type if response.data.carrier else None,
},
"line_type": response.data.line_type,
"number_type": response.data.number_type,
"portability": {
"status": response.data.portability.status if response.data.portability else None,
"last_checked_at": response.data.portability.last_checked_at if response.data.portability else None,
},
"from_cache": False,
}
cache_lookup_result(phone_number, lookup_data)
return lookup_data
Caching
The cache is a Python dict with a 24-hour TTL. Each entry stores the lookup result and a timestamp. is_cache_valid() compares the stored timestamp against the TTL, and expired entries are replaced on the next lookup.
This keeps repeated lookups of the same number free — the Telnyx API is only called once per number per 24-hour window.
Error Handling
The Flask endpoints catch Telnyx SDK exceptions and return appropriate HTTP status codes:
-
401for invalid API keys -
429for rate limit hits -
503for network errors -
400for malformed requests
Test It
Look up a number (POST):
curl -X POST http://localhost:5000/lookup \
-H "Content-Type: application/json" \
-d '{"phone_number": "+15551234567"}'
Look up a number (GET):
curl http://localhost:5000/lookup/+15551234567
Check the cache:
curl http://localhost:5000/cache/stats
Run the same lookup twice — the second response returns "from_cache": true.
Going to Production
This example uses an in-memory cache for simplicity. For production:
- Shared cache — Replace the in-memory dict with Redis so the cache survives restarts and is shared across instances.
- Authentication — Add API key validation on your endpoints so the lookup service is not open to the internet.
- Rate limiting — Protect your endpoints and stay within Telnyx Number Lookup limits.
- Persistence — Store lookup history in a database if you need an audit trail.
- Monitoring — Add structured logging and alert on error rates.
Resources
- Code example: https://github.com/team-telnyx/telnyx-code-examples/tree/main/phone-number-lookup-python
- Number Lookup Guide: https://developers.telnyx.com/docs/identity/number-lookup
- Number Lookup API Reference: https://developers.telnyx.com/api-reference/number-lookup/retrieve-lookup
- Python SDK: https://developers.telnyx.com/development/sdk/python
- Telnyx Portal: https://portal.telnyx.com
Related Examples
- number-lookup-fraud-screener-python — Screen inbound numbers for fraud before connecting
- number-lookup-lead-enrichment-python — Enrich sales leads with carrier and CNAM data
- cnam-caller-id-lookup-enrichment-python — CNAM caller ID enrichment
- bulk-number-validation-cleaner-python — Validate and clean lists of numbers
Top comments (0)