Telnyx API integration for Clawdbot. Send SMS/email/WhatsApp messages, manage phone numbers, query call logs, debug webhooks, and access your Telnyx account....
---
name: telnyx-cli
description: "Telnyx API integration for Clawdbot. Send SMS/email/WhatsApp messages, manage phone numbers, query call logs, debug webhooks, and access your Telnyx account. Use when you need to interact with Telnyx APIs via CLI, manage phone numbers and messaging, debug webhooks, or access account data."
metadata:
clawdbot:
emoji: "📞"
requires:
bins: ["telnyx"]
env: []
notes: "API key stored in ~/.config/telnyx/config.json after 'telnyx auth setup'"
---
# Telnyx CLI
Telnyx API integration for Clawdbot: messaging, phone numbers, webhooks, and account management.
## Setup
### 1. Install CLI
```bash
npm install -g @telnyx/api-cli
```
### 2. Configure API Key
```bash
telnyx auth setup
```
Paste your API key from: https://portal.telnyx.com/#/app/api-keys
Saves to `~/.config/telnyx/config.json` (persistent).
### 3. Verify
```bash
telnyx number list
```
## Commands
| Category | Command | Description |
|----------|---------|-------------|
| **Messaging** | `telnyx message send` | Send SMS/email/WhatsApp |
| | `telnyx message list` | List messages |
| | `telnyx message get` | Get message status |
| **Phone Numbers** | `telnyx number list` | Your phone numbers |
| | `telnyx number search` | Search available numbers |
| | `telnyx number buy` | Purchase a number |
| | `telnyx number release` | Release a number |
| **Calls** | `telnyx call list` | View calls |
| | `telnyx call get` | Get call details |
| **Webhooks** | `telnyx webhook list` | List webhooks |
| | `telnyx debugger list` | View webhook events |
| | `telnyx debugger retry` | Retry failed webhooks |
| **Account** | `telnyx account get` | Account info & balance |
## Usage
### Messaging
```bash
# Send SMS
telnyx message send --from +15551234567 --to +15559876543 --text "Hello!"
# List messages
telnyx message list
# Get status
telnyx message get MESSAGE_ID
```
### Phone Numbers
```bash
# List
telnyx number list
# Search
telnyx number search --country US --npa 415
# Buy
telnyx number buy --number "+15551234567"
# Release
telnyx number release "+15551234567"
```
### Webhooks & Debugging
```bash
# List webhooks
telnyx webhook list
# View failed deliveries
telnyx debugger list --status failed
# Retry failed
telnyx debugger retry EVENT_ID
```
### Account
```bash
# Account info
telnyx account get
# Check balance
telnyx account get --output json | jq '.balance'
```
## Output Formats
```bash
# Table (default)
telnyx number list
# JSON
telnyx number list --output json
# CSV
telnyx number list --output csv
```
## Examples
### Bulk Messaging
```bash
#!/bin/bash
while read phone; do
telnyx message send --from +15551234567 --to "$phone" --text "Hello!"
sleep 1 # Rate limiting
done < recipients.txt
```
### Monitor Webhooks
```bash
#!/bin/bash
while true; do
FAILED=$(telnyx debugger list --status failed --output json | jq '.data | length')
[ "$FAILED" -gt 0 ] && echo "⚠️ $FAILED failed webhooks"
sleep 300
done
```
### Export Data
```bash
# CSV export
telnyx call list --limit 1000 --output csv > calls.csv
# JSON export
telnyx number list --output json > numbers.json
```
## Tips
- Rate limit: 100 req/s — add `sleep 1` for bulk operations
- Use `--output json` or `--output csv` to change format
- Get help: `telnyx COMMAND --help` (e.g., `telnyx message --help`)
- API Key location: `~/.config/telnyx/config.json`
## Integration with Clawdbot
```bash
# In cron jobs
0 9 * * * telnyx call list --limit 10 > /tmp/daily-calls.txt
# In heartbeat
telnyx debugger list --status failed
# In scripts
BALANCE=$(telnyx account get --output json | jq '.balance')
echo "Balance: $BALANCE"
```
## Companion Skills
This skill is the primary Telnyx interface. Two companion skills handle account lifecycle steps that this skill cannot:
| Skill | Purpose | Install |
|-------|---------|---------|
| **telnyx-bot-signup** | Create a new account OR sign into an existing one (generates API key) | `clawhub install telnyx-bot-signup` |
| **telnyx-freemium-upgrade** | Upgrade freemium account to professional tier | `clawhub install telnyx-freemium-upgrade` |
> **Note:** `telnyx-bot-signup` handles both signup and signin. The `bot_signup` endpoint accepts both new and existing emails — it sends a magic sign-in link either way. The flow is identical: PoW challenge → email → magic link → session token → API key.
### Pre-flight: Before Any Telnyx Operation
Before executing a Telnyx CLI command, run through this checklist:
```
1. Is `telnyx` CLI installed?
NO → npm install -g @telnyx/api-cli
2. Does ~/.config/telnyx/config.json exist with an api_key?
NO → Hand off to **telnyx-bot-signup** (see below)
Works for both new AND existing accounts.
3. Does `telnyx account get` succeed?
NO (401 auth error) → API key is invalid/expired.
Hand off to **telnyx-bot-signup** to generate a fresh key.
NO (network error) → Check connectivity.
YES → Proceed with the requested operation.
```
### When to Hand Off to telnyx-bot-signup
Hand off to the **telnyx-bot-signup** skill when ANY of these are true:
- No API key exists (`~/.config/telnyx/config.json` missing or empty, no `TELNYX_API_KEY` env var)
- API key exists but `telnyx account get` returns 401 (key invalid/expired/revoked)
- User says they lost their API key or can't access the portal
- User wants to create a new Telnyx account
**Do NOT ask whether the user has an account or not.** The `bot_signup` endpoint handles both cases transparently — just ask for their email and proceed.
**What telnyx-bot-signup does:** PoW challenge → submit email → magic sign-in link sent to email → session token → `POST /v2/api_keys` → fresh API key. Works identically for new and existing accounts.
**After signup/signin completes:**
1. Store the returned API key:
```bash
mkdir -p ~/.config/telnyx
echo '{"api_key":"<KEY_FROM_SIGNUP>"}' > ~/.config/telnyx/config.json
```
2. Also export it for the current session:
```bash
export TELNYX_API_KEY="<KEY_FROM_SIGNUP>"
```
3. If the account is new, it starts on **freemium** tier. Return here and proceed with the original operation. If it hits a freemium wall, the upgrade flow below will trigger automatically.
### When to Hand Off to telnyx-freemium-upgrade
Hand off to the **telnyx-freemium-upgrade** skill when a CLI command fails with a freemium restriction. Detect these scenarios:
| Trigger | How you see it | Example |
|---------|---------------|---------|
| **Error 10039** | SMS send fails: "destination not verified" | `telnyx message send --to +39... --text "test"` |
| **Error D60** | Voice call fails: "destination not verified" | Outbound call to unverified number |
| **Error 10038** | Feature blocked: "not available on current plan" | Porting, short codes, SIM, managed accounts |
| **Number limit hit** | Second `telnyx number buy` fails | Already have 1 number (freemium max) |
| **Cannot add funds** | Balance top-up or payment method rejected | Freemium accounts cannot add balance |
| **Account inactive/deactivated** | Account shows deactivated due to $0 balance | `telnyx account get` shows inactive status |
**Also trigger proactively** when the user's intent clearly requires professional tier before even making the API call:
| User says | Why it needs upgrade |
|-----------|---------------------|
| "Send SMS to +39..." (international) | Unverified destination (10039) |
| "Port my number from AT&T" | Porting blocked on freemium (10038) |
| "Buy 5 phone numbers" | 1 number limit on freemium |
| "Set up a SIP trunk" | SIP blocked on freemium (10038) |
| "Create a managed account" | Managed accounts blocked (10038) |
| "Add $50 to my balance" | Freemium can't add funds |
Before handing off, check if the upgrade was already attempted:
```
1. Read ~/.telnyx/upgrade.json (cache from the upgrade skill)
2. If decision == "APPROVED"
→ Account is already upgraded. Do NOT hand off.
Retry the operation directly. If it still fails, the API key
may need to be refreshed: telnyx auth setup
3. If decision == "REJECTED" and used_methods includes "github_oauth"
→ GitHub method exhausted. Do NOT hand off.
Tell the user: "Your upgrade was not approved. Contact
support at https://support.telnyx.com or try LinkedIn
verification when available."
4. If decision == "PASS_TO_HUMAN"
→ Under manual review. Do NOT hand off.
Tell the user: "Your upgrade is under review. I'll check
back periodically." (The upgrade skill's cron job handles this.)
5. If no cache or status is "failed" / "polling_timeout"
→ Hand off to **telnyx-freemium-upgrade**.
```
**After upgrade completes (APPROVED):**
1. Retry the original operation that triggered the upgrade.
2. If the retry still fails with the same error, the API key needs to be refreshed to pick up professional-tier permissions. Use **telnyx-bot-signup** to generate a fresh key (same email, sign-in flow) — this is easier than asking the user to visit the portal.
### Full Lifecycle Flow
```
User: "Send SMS to +393406879636"
│
├── telnyx CLI installed? ──NO──→ npm install -g @telnyx/api-cli
│
├── API key configured? ──NO──→ **telnyx-bot-signup** (ask for email)
│ → PoW → magic link → API key
│ → Store key → continue
│
├── API key valid? (`telnyx account get`)
│ └── NO (401) → **telnyx-bot-signup** (ask for email)
│ → PoW → magic link → fresh API key
│ → Store key → continue
│
├── telnyx message send --from ... --to +39... --text "..."
│ │
│ ├── Success → Done
│ │
│ └── Error 10039 (destination not verified)
│ │
│ ├── Check upgrade cache (~/.telnyx/upgrade.json)
│ │ ├── APPROVED → Retry (key may need refresh)
│ │ ├── REJECTED → Inform user, suggest support
│ │ ├── PASS_TO_HUMAN → Inform user, wait for review
│ │ └── No cache / failed → Continue to upgrade
│ │
│ └── **telnyx-freemium-upgrade** → GitHub verification → poll
│ │
│ ├── APPROVED → retry SMS (key may need refresh via bot-signup)
│ ├── REJECTED → Inform user
│ └── PASS_TO_HUMAN → Cron job polls, notify on resolution
```
### Companion Skill Not Installed
If you need to hand off but the companion skill is not installed:
**telnyx-bot-signup missing:**
> I need to set up your Telnyx API key. Install the signup/signin skill:
> ```
> clawhub install telnyx-bot-signup
> ```
> Or get your API key manually from https://portal.telnyx.com/#/app/api-keys and run `telnyx auth setup`
**telnyx-freemium-upgrade missing:**
> Your account is on the freemium tier, which doesn't support this operation. Install the upgrade skill:
> ```
> clawhub install telnyx-freemium-upgrade
> ```
> Or upgrade manually via https://portal.telnyx.com/#/account/account-levels/upgrade
---
## Troubleshooting
### CLI not found
```bash
npm install -g @telnyx/api-cli
```
### API key not configured
```bash
# Reconfigure
telnyx auth setup
# Or check existing config
cat ~/.config/telnyx/config.json
```
### Connection issues
```bash
# Test connection
telnyx account get
```
## Resources
- Telnyx Docs: https://developers.telnyx.com
- API Portal: https://portal.telnyx.com
- Telnyx CLI: https://github.com/team-telnyx/telnyx-api-cli
don't have the plugin yet? install it then click "run inline in claude" again.
this skill lets you interact with the Telnyx API through the command line to send messages across SMS, email, and WhatsApp, manage phone numbers, monitor webhooks, query call history, and check account balance. use it when you need to send bulk messages, search for available phone numbers, debug failed webhooks, or pull account data from Telnyx without touching the web portal.
required binaries:
telnyx (npm global package: npm install -g @telnyx/api-cli)required credentials:
~/.config/telnyx/config.json after running telnyx auth setupTELNYX_API_KEY environment variable for the current sessionexternal connection:
companion skills for account lifecycle:
telnyx-bot-signup: creates new Telnyx accounts or signs into existing ones. hand off when API key is missing, invalid (401 error), or user needs to generate a fresh key.telnyx-freemium-upgrade: upgrades freemium accounts to professional tier. hand off when CLI commands fail with error 10039 (unverified destination), error D60 (voice blocked), error 10038 (feature not available on current plan), or when you hit freemium limits (1 phone number max, cannot add funds).0. pre-flight check (do this before any telnyx CLI command)
npm list -g @telnyx/api-cli or attempt telnyx --versionnpm install -g @telnyx/api-cli and re-check0a. verify API key exists and is valid
telnyx account get to test authentication1. send SMS/email/WhatsApp message
telnyx message send --from <SENDER> --to <RECIPIENT> --text "<MESSAGE>" (or --email-from/--email-to for email, --whatsapp-from/--whatsapp-to for WhatsApp)2. list sent or received messages
telnyx message list [--status sent|received] [--start-time TIMESTAMP] [--end-time TIMESTAMP]3. get message status
telnyx message get <MESSAGE_ID>4. list phone numbers owned by account
telnyx number list [--limit N]5. search for available phone numbers
telnyx number search --country <COUNTRY> --npa <AREA_CODE> [--number-type local|mobile|toll-free]6. purchase a phone number
telnyx number buy --number "<PHONE_NUMBER>"7. release a phone number
telnyx number release "<PHONE_NUMBER>"8. list call logs
telnyx call list [--limit N] [--direction inbound|outbound]9. get call details
telnyx call get <CALL_ID>10. list webhooks
telnyx webhook list11. view webhook delivery events (debugger)
telnyx debugger list [--status failed] [--limit N]12. retry a failed webhook delivery
telnyx debugger retry <EVENT_ID>13. get account info and balance
telnyx account get [--output json]14. change output format
--output json or --output csv to any listing commandafter pre-flight check (step 0a), determine next action:
telnyx account get returns 200 with account data: proceed to user's requested operation (steps 1-14).telnyx account get returns 401 (Unauthorized): API key is invalid, expired, or revoked. hand off to telnyx-bot-signup (ask for email, generate fresh key, store in ~/.config/telnyx/config.json).telnyx account get returns 4xx other than 401: API key exists but has a validation or permissions issue. retry with telnyx auth setup to reconfigure.telnyx account get fails with network error (connection refused, timeout, DNS failure): check network connectivity and Telnyx API status. retry after 30 seconds.telnyx-bot-signup.during messaging, calling, or number operations, if operation fails, check error code:
~/.telnyx/upgrade.json. if cache shows APPROVED, retry command (may need fresh API key from telnyx-bot-signup). if cache shows REJECTED, tell user upgrade was denied, suggest support. if cache missing or failed, hand off to telnyx-freemium-upgrade.telnyx-freemium-upgrade.telnyx number buy saying number limit exceeded: freemium max is 1 number. hand off to telnyx-freemium-upgrade for upgrade.telnyx-freemium-upgrade.telnyx-bot-signup for fresh key.sleep 1 between requests in bulk scripts or implement exponential backoff.--limit or paginate. Telnyx CLI defaults to limit 100; max is 1000.proactively trigger freemium upgrade before making API call if user intent clearly requires professional tier:
all CLI commands return data in one of three formats:
table format (default):
telnyx number list prints phone numbers with country, status, cost columnsJSON format (append --output json):
data array and metadata{"data": [<objects>], "metadata": {"total": N, "page": P}}jq or storing in filestelnyx account get --output json returns account object as valid JSONCSV format (append --output csv):
telnyx call list --output csv > calls.csv writes to filefile storage locations:
~/.config/telnyx/config.json (JSON with {"api_key": "KEY_VALUE"})~/.telnyx/upgrade.json (set by companion skill, read by this skill to avoid redundant upgrades)success response examples:
sending a message returns:
{
"data": {
"record_type": "message",
"id": "msg_ABC123",
"from": "+15551234567",
"to": "+15559876543",
"text": "Hello!",
"status": "queued",
"created_at": "2024-01-15T10:30:00Z"
}
}
listing numbers returns:
{
"data": [
{
"record_type": "phone_number",
"phone_number": "+15551234567",
"status": "active",
"country": "US",
"capabilities": ["sms", "voice"],
"monthly_cost": 1.25
}
],
"metadata": {"total": 1, "page": 1}
}
checking account returns:
{
"data": {
"record_type": "account",
"id": "acc_XYZ789",
"status": "active",
"plan_tier": "freemium",
"balance_cents": 5000,
"phone_numbers_count": 1
}
}
the skill worked if:
after install and setup: telnyx --version prints version number, and telnyx account get succeeds with 200 response and your account email visible in the output.
after sending a message: telnyx message send returns a message ID and status "queued" or "sent" within 2 seconds. check delivery with telnyx message get <ID> to confirm status changes to "sent" or "delivered" (SMS typically confirms within 5 seconds, email within 10 seconds).
after listing/searching numbers: output includes at least one row (for list) or multiple rows (for search). check that phone numbers are properly formatted (+country code and digits) and status is either "active" (for owned numbers) or "available" (for search results).
after purchasing a number: output shows the number with status "active" and a confirmation message. verify by running telnyx number list again and seeing the new number in the list.
after querying call logs: output includes call records with start/end times and durations in seconds. verify timestamps are recent and match your call activity.
after listing webhooks or debugger events: output shows webhook URLs or event records. if you previously sent webhooks, check that event count matches expected message or call volume.
after retrying a failed webhook: debugger output shows the event with new delivery timestamp and response code (should be 2xx if the retry succeeded).
bulk operations (loops, exports): all messages in the loop sent without rate limit errors (if looping with sleep 1). exported CSV or JSON files are valid (can open in spreadsheet or parse with jq).
troubleshooting commands work: telnyx auth setup completes without errors, API key is written to config file, and subsequent telnyx account get succeeds.
if any command returns 4xx or 5xx, check the error message. if it's 10039, 10038, D60, or mentions freemium, refer to decision points for upgrade flow. if it's 401, API key is stale; re-run telnyx auth setup. if it's a timeout or 5xx, retry after 10 seconds or check Telnyx status page.
npm install -g @telnyx/api-cli
telnyx auth setup
paste your API key from https://portal.telnyx.com/#/app/api-keys. saves to ~/.config/telnyx/config.json (persistent).
telnyx number list
| category | command | description |
|---|---|---|
| messaging | telnyx message send |
send SMS/email/WhatsApp |
telnyx message list |
list messages | |
telnyx message get |
get message status | |
| phone numbers | telnyx number list |
your phone numbers |
telnyx number search |
search available numbers | |
telnyx number buy |
purchase a number | |
telnyx number release |
release a number | |
| calls | telnyx call list |
view calls |
telnyx call get |
get call details | |
| webhooks | telnyx webhook list |
list webhooks |
telnyx debugger list |
view webhook events | |
telnyx debugger retry |
retry failed webhooks | |
| account | telnyx account get |
account info and balance |
# send SMS
telnyx message send --from +15551234567 --to +15559876543 --text "Hello!"
# list messages
telnyx message list
# get status
telnyx message get MESSAGE_ID
# list
telnyx number list
# search
telnyx number search --country US --npa 415
# buy
telnyx number buy --number "+15551234567"
# release
telnyx number release "+15551234567"
# list webhooks
telnyx webhook list
# view failed deliveries
telnyx debugger list --status failed
# retry failed
telnyx debugger retry EVENT_ID
# account info
telnyx account get
# check balance
telnyx account get --output json | jq '.balance'
# table (default)
telnyx number list
# JSON
telnyx number list --output json
# CSV
telnyx number list --output csv
#!/bin/bash
while read phone; do
telnyx message send --from +15551234567 --to "$phone" --text "Hello!"
sleep 1 # rate limiting
done < recipients.txt
#!/bin/bash
while true; do
FAILED=$(telnyx debugger list --status failed --output json | jq '.data | length')
[ "$FAILED" -gt 0 ] && echo "WARNING: $FAILED failed webhooks"
sleep 300
done
# CSV export
telnyx call list --limit 1000 --output csv > calls.csv
# JSON export
telnyx number list --output json > numbers.json
sleep 1 for bulk operations.--output json or --output csv to change format.telnyx COMMAND --help (e.g., telnyx message --help).~/.config/telnyx/config.json.--limit 1000 to fetch max results.telnyx debugger list again if immediate recheck fails.# in cron jobs
0 9 * * * telnyx call list --limit 10 > /tmp/daily-calls.txt
# in heartbeat
telnyx debugger list --status failed
# in scripts
BALANCE=$(telnyx account get --output json | jq '.data.balance_cents')
echo "Balance: $BALANCE cents"
this skill is the primary Telnyx interface. two companion skills handle account lifecycle operations that this skill cannot:
| skill | purpose | install |
|---|---|---|
| telnyx-bot-signup | create a new account OR sign into an existing one (generates API key) | clawhub install telnyx-bot-signup |
| telnyx-freemium-upgrade | upgrade freemium account to professional tier | clawhub install telnyx-freemium-upgrade |
note: telnyx-bot-signup handles both signup and signin. the bot_signup endpoint accepts both new and existing emails, sending a magic sign-in link either way. the flow is identical: PoW challenge, email, magic link, session token, API key.
before executing a Telnyx CLI command, run through this checklist:
1. Is `telnyx` CLI installed?
NO → npm install -g @telnyx/api-cli
2. Does ~/.config/telnyx/config.json exist with an api_key?
NO → Hand off to telnyx-bot-signup (see below)
Works for both new AND existing accounts.
3. Does `telnyx account get` succeed?
NO (401 auth error) → API key is invalid/expired.
Hand off to telnyx-bot-signup to generate a fresh key.
NO (network error) → Check connectivity.
YES → Proceed with the requested operation.
hand off to the telnyx-bot-signup skill when any of these are true:
~/.config/telnyx/config.json missing or empty, no TELNYX_API_KEY env var)telnyx account get returns 401 (key invalid/expired/revoked)do NOT ask whether the user has an account or not. the bot_signup endpoint handles both cases transparently. just ask for their email and proceed.
what telnyx-bot-signup does: PoW challenge, submit email, magic sign-in link sent to email, session token, POST /v2/api_keys, fresh API key. works identically for new and existing accounts.
after signup/signin completes:
mkdir -p ~/.config/telnyx
echo '{"api_key":"<KEY_FROM_SIGNUP>"}' > ~/.config/telnyx/config.json
export TELNYX_API_KEY="<KEY_FROM_SIGNUP>"
hand off to the telnyx-freemium-upgrade skill when a CLI command fails with a freemium restriction. detect these scenarios:
| trigger | how you see it | example |
|---|---|---|
| error 10039 | SMS send fails: "destination not verified" | telnyx message send --to +39... --text "test" |
| error D60 | voice call fails: "destination not verified" | outbound call to unverified number |
| error 10038 | feature blocked: "not available on current plan" | porting, short codes, SIM, managed accounts |
| number limit hit | second telnyx number buy fails |
already have 1 number (freemium max) |
| cannot add funds | balance top-up or payment method rejected | freemium accounts cannot add balance |
| account inactive/deactivated | account shows deactivated due to zero balance | telnyx account get shows inactive status |
also trigger proactively when the user's intent clearly requires professional tier before even making the API call:
| user says | why it needs upgrade |
|---|---|
| "send SMS to +39..." (international) | unverified destination (10039) |
| "port my number from AT&T" | porting blocked on freemium (10038) |
| "buy 5 phone numbers" | 1 number limit on freemium |
| "set up a SIP trunk" | SIP blocked on freemium (10038) |
| "create a managed account" | managed accounts blocked (10038) |
| "add $50 to my balance" | freemium cannot add funds |
before handing off, check if the upgrade was already attempted:
1. read ~/.telnyx/upgrade.json (cache from the upgrade skill)
2. if decision == "APPROVED"
→ Account is already upgraded. do NOT hand off.
retry the operation directly. if it still fails, the API key
may need to be refreshed: telnyx auth setup
3. if decision == "REJECTED" and used_methods includes "github_oauth"
→ GitHub method exhausted. do NOT hand off.
tell the user: "Your upgrade was not approved. contact
support at https://support.telnyx.com or try LinkedIn
verification when available."
4. if decision == "PASS_TO_HUMAN"
→ Under manual review. do NOT hand off.
tell the user: "Your upgrade is under review. I'll check
back periodically." (the upgrade skill's cron job handles this.)
5. if no cache or status is "failed" / "polling_timeout"
→ hand off to telnyx-freemium-upgrade.
after upgrade completes (APPROVED):
retry the original operation that triggered the upgrade.
if the retry still fails with the same error, the API key needs to be refreshed to pick up professional-tier permissions. use telnyx-bot-signup to generate a fresh key (same email, sign-in flow) , this is easier than asking the user to visit the portal.
User: "Send SMS to +393406879636"
│
├── telnyx CLI installed? ──NO──→ npm install -g @telnyx/api-cli
│
├── API key configured? ──NO──→ telnyx-bot-signup (ask for email)
│ → PoW → magic link → API key
│ → store key → continue
│
├── API key valid? (telnyx account get)
│ └── NO (401) → telnyx-bot-signup (ask for email)
│ → PoW → magic link → fresh API key
│ → store key → continue
│
├── telnyx message send --from ... --to +39... --text "..."
│ │
│ ├── success → Done
│ │
│ └── error 10039 (destination not verified)
│ │
│ ├── check upgrade cache (~/.telnyx/upgrade.json)
│ │ ├── APPROVED → retry (key may need refresh)
│ │ ├── REJECTED → inform user, suggest support
│ │ ├── PASS_TO_HUMAN → inform user, wait for review
│ │ └── no cache / failed → continue to upgrade
│ │
│ └── telnyx-freemium-upgrade → GitHub verification → poll
│ │
│ ├── APPROVED → retry SMS (key may need refresh via bot-signup)
│ ├── REJECTED → inform user
│ └── PASS_TO_HUMAN → cron job polls, notify on resolution
if you need to hand off but the companion skill