# Telnyx API

> Use this skill when working with Telnyx communication APIs for SMS/MMS messaging, voice calls, phone number management, messaging profiles, webhook integration, two-way SMS conversations, bulk sending, message scheduling, or production deployment of telephony features. Applies to building communication features, SMS notification systems, voice IVR systems, or integrating telephony capabilities.

- Skill: `tdimino/telnyx-api` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add tdimino/telnyx-api`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tdimino/telnyx-api/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: tdimino (https://skillmd.com/u/tdimino)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tdimino/telnyx-api

---


# Telnyx API - Comprehensive Communication Platform

## When to Use This Skill

Use this skill when working with Telnyx's communication APIs for:

- **SMS/MMS Messaging** - Send and receive text messages programmatically
- **Voice Communication** - Build voice calling applications with Call Control API
- **Phone Number Management** - Search, purchase, and configure phone numbers
- **Messaging Profiles** - Configure messaging settings and webhooks
- **Webhook Integration** - Handle real-time events and delivery notifications
- **Two-Way SMS Conversations** - Build interactive SMS experiences
- **Bulk SMS Sending** - Send messages to multiple recipients with rate limiting
- **Message Scheduling** - Schedule messages for future delivery
- **Production Deployment** - Deploy messaging features with error handling and monitoring

This skill applies to building communication features in applications, setting up SMS notification systems, creating voice IVR systems, or integrating telephony capabilities.

## Quick Reference

### 1. Send Simple SMS
```javascript
const axios = require('axios');

async function sendSMS(to, from, text) {
  const response = await axios.post(
    'https://api.telnyx.com/v2/messages',
    { from, to, text },
    {
      headers: {
        'Authorization': `Bearer ${process.env.TELNYX_API_KEY}`,
        'Content-Type': 'application/json'
      }
    }
  );
  return response.data;
}

// Usage
sendSMS('+14155552671', '+14155559999', 'Hello from Telnyx!');
```

### 2. Send MMS with Media
```javascript
async function sendMMS(to, from, text, mediaUrls) {
  const response = await axios.post(
    'https://api.telnyx.com/v2/messages',
    {
      from,
      to,
      text,
      media_urls: mediaUrls,
      type: 'MMS'
    },
    {
      headers: {
        'Authorization': `Bearer ${process.env.TELNYX_API_KEY}`,
        'Content-Type': 'application/json'
      }
    }
  );
  return response.data;
}

// Usage
sendMMS('+14155552671', '+14155559999', 'Check this out!',
  ['https://example.com/image.jpg']);
```

### 3. Handle Incoming Messages (Webhook)
```javascript
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhooks/telnyx', (req, res) => {
  const event = req.body.data;

  if (event.event_type === 'message.received') {
    const from = event.payload.from.phone_number;
    const text = event.payload.text;
    const to = event.payload.to[0].phone_number;

    console.log(`Received: "${text}" from ${from}`);

    // Auto-reply
    sendSMS(from, to, 'Thanks for your message!');
  }

  res.status(200).send('OK');
});
```

### 4. Validate Phone Numbers
```javascript
function validateE164(phoneNumber) {
  const e164Regex = /^\+[1-9]\d{1,14}$/;

  if (!e164Regex.test(phoneNumber)) {
    return {
      valid: false,
      error: 'Phone number must be in E.164 format (e.g., +14155552671)'
    };
  }

  return { valid: true };
}

// Usage
const validation = validateE164('+14155552671');
if (!validation.valid) {
  throw new Error(validation.error);
}
```

### 5. Send with Error Handling
```javascript
async function sendWithRetry(to, from, text, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sendSMS(to, from, text);
    } catch (error) {
      if (error.response?.status === 500 && attempt < maxRetries) {
        const delayMs = Math.pow(2, attempt) * 1000;
        console.log(`Retry in ${delayMs}ms...`);
        await new Promise(resolve => setTimeout(resolve, delayMs));
      } else {
        throw error;
      }
    }
  }
}
```

### 6. Bulk Sending with Rate Limiting
```javascript
async function sendBulkSMS(recipients, from, text) {
  const delayMs = 100; // 10 messages/second
  const results = [];

  for (const recipient of recipients) {
    try {
      const result = await sendSMS(recipient, from, text);
      results.push({ success: true, to: recipient, id: result.data.id });
    } catch (error) {
      results.push({ success: false, to: recipient, error: error.message });
    }

    await new Promise(resolve => setTimeout(resolve, delayMs));
  }

  return results;
}
```

### 7. Verify Webhook Signatures
```javascript
const crypto = require('crypto');

function verifyWebhook(body, signature, timestamp, publicKey) {
  // Check timestamp freshness (prevent replay attacks)
  const timestampMs = parseInt(timestamp);
  const now = Date.now();
  if (Math.abs(now - timestampMs) > 5 * 60 * 1000) {
    return false; // Reject if older than 5 minutes
  }

  // Verify signature
  const payload = `${timestamp}.${JSON.stringify(body)}`;
  const hmac = crypto.createHmac('sha256', publicKey);
  const digest = hmac.update(payload).digest('hex');

  return signature === digest;
}

// Usage
app.post('/webhooks/telnyx', (req, res) => {
  const signature = req.headers['telnyx-signature-ed25519'];
  const timestamp = req.headers['telnyx-timestamp'];

  if (!verifyWebhook(req.body, signature, timestamp, process.env.TELNYX_PUBLIC_KEY)) {
    return res.status(401).send('Invalid signature');
  }

  // Process webhook...
  res.status(200).send('OK');
});
```

### 8. Schedule Message for Later
```javascript
async function scheduleMessage(to, from, text, sendAt) {
  const response = await axios.post(
    'https://api.telnyx.com/v2/messages',
    {
      from,
      to,
      text,
      send_at: sendAt  // ISO 8601: "2025-10-25T14:30:00Z"
    },
    {
      headers: {
        'Authorization': `Bearer ${process.env.TELNYX_API_KEY}`,
        'Content-Type': 'application/json'
      }
    }
  );
  return response.data;
}

// Schedule for 1 hour from now
const futureTime = new Date(Date.now() + 3600000).toISOString();
scheduleMessage('+14155552671', '+14155559999', 'Reminder!', futureTime);
```

### 9. Two-Way Conversation Flow
```javascript
const conversations = new Map();

app.post('/webhooks/telnyx', async (req, res) => {
  const event = req.body.data;

  if (event.event_type === 'message.received') {
    const from = event.payload.from.phone_number;
    const to = event.payload.to[0].phone_number;
    const text = event.payload.text.toLowerCase();

    let state = conversations.get(from) || 'start';
    let reply;

    switch (state) {
      case 'start':
        reply = "Welcome! What's your name?";
        conversations.set(from, 'asked_name');
        break;

      case 'asked_name':
        reply = `Nice to meet you, ${text}! How can I help?`;
        conversations.set(from, 'helping');
        break;

      case 'helping':
        reply = 'Thanks! A human will respond shortly.';
        conversations.delete(from);
        break;
    }

    await sendSMS(from, to, reply);
  }

  res.status(200).send('OK');
});
```

### 10. Python Example
```python
import requests
import os

def send_sms(to, from_number, text):
    url = 'https://api.telnyx.com/v2/messages'
    headers = {
        'Authorization': f"Bearer {os.environ['TELNYX_API_KEY']}",
        'Content-Type': 'application/json'
    }
    payload = {
        'from': from_number,
        'to': to,
        'text': text
    }

    response = requests.post(url, json=payload, headers=headers)
    response.raise_for_status()

    return response.json()

# Usage
result = send_sms('+14155552671', '+14155559999', 'Hello from Python!')
print(f"Message ID: {result['data']['id']}")
```

## Key Concepts

### 1. E.164 Phone Number Format
International phone number format: `+[country code][number]`
- US Example: `+14155552671`
- UK Example: `+442071234567`
- Always include the `+` prefix

### 2. Messaging Profile
A configuration container that groups numbers and defines webhook settings. Benefits:
- Centralized webhook management
- Number pools for load distribution
- Alphanumeric sender IDs
- Easy number management

### 3. Message Encoding
- **GSM-7**: 160 chars/segment for standard ASCII (cheaper)
- **UCS-2**: 70 chars/segment for emoji/unicode (more expensive)
- Long messages split into segments (max 10)
- Multi-part messages: GSM-7 = 153 chars/segment, UCS-2 = 67 chars/segment

### 4. Webhook Events
Real-time notifications about message status:
- `message.sent` - Sent to carrier
- `message.delivered` - Delivered to recipient
- `message.failed` - Delivery failed
- `message.received` - Inbound message received
- `message.finalized` - Reached final state

### 5. Authentication
All API requests require Bearer token authentication:
```
Authorization: Bearer YOUR_API_KEY
```
Store API keys in environment variables, never hardcode.

## Reference Files

The `references/` directory contains detailed documentation:

### authentication.md
Complete guide to API key management and security:
- Creating and managing API keys
- Environment variable setup (Node.js, Python, Docker, Kubernetes)
- Best practices for key rotation and security
- IP whitelisting configuration
- Webhook signature verification
- Common authentication errors and solutions

### messaging-api.md
Full Messaging API reference:
- Complete endpoint documentation (`/v2/messages`)
- All request/response parameters
- Message status values and lifecycle
- Character encoding details (GSM-7 vs UCS-2)
- Message segmentation rules
- MMS limitations and supported formats
- Pagination and filtering options

### webhooks.md
Comprehensive webhook reference:
- All webhook event types with payload examples
- Signature verification (HMAC-SHA256)
- Webhook configuration (global, profile, per-message)
- Best practices (idempotency, async processing, retries)
- Testing webhooks locally with ngrok
- Complete webhook handler example
- Troubleshooting guide

### error-codes.md
Complete error reference and handling:
- All HTTP status codes and meanings
- Common error codes with solutions
- Validation errors (10001-10007)
- Rate limiting errors (429)
- Server errors (500, 502, 503)
- Webhook-specific delivery errors
- Comprehensive error handler implementation
- Retry strategies with backoff

### best-practices.md
Production deployment patterns:
- Using messaging profiles in production
- Robust error handling patterns
- Exponential backoff retry logic
- Rate limiting for bulk sending
- Message tracking and status monitoring
- Phone number validation and formatting
- Message content optimization
- Character limit handling
- Webhook async processing with queues
- Idempotency implementation
- Structured logging and monitoring
- Cost optimization strategies
- Testing patterns
- Production deployment checklist

### number-management.md
Phone number operations:
- Searching available numbers
- Purchasing phone numbers
- Configuring number settings
- Porting existing numbers
- Number pool management

### 10dlc.md
10DLC (10-Digit Long Code) registration and compliance:
- Campaign approval stages (TCR_ACCEPTED → MNO_PENDING → MNO_PROVISIONED)
- Brand and campaign registration process
- Use case selection (Customer Care, Marketing, 2FA, etc.)
- TCPA and CTIA compliance requirements
- Required message elements (opt-in, opt-out, HELP)
- Monitoring campaign status via API
- Phone number association (portal-only, not via API)
- Cost structure and timeline expectations
- Common issues and troubleshooting
- Production checklist

## Working with This Skill

### For Beginners

**Start Here:**
1. Use **Quick Reference Example #1** (Send Simple SMS)
2. Set up environment variables for API key
3. Test sending to your own phone number
4. Set up **Quick Reference Example #3** (Handle Incoming Messages)
5. Test two-way messaging

**Key Concepts to Learn:**
- E.164 phone number format
- Bearer token authentication
- Basic webhook handling

**Reference Files:**
- Start with `authentication.md` for setup
- Check `messaging-api.md` for basic API usage
- Review `error-codes.md` when errors occur

### For Intermediate Users

**Focus Areas:**
1. Implement **Quick Reference Example #7** (Verify Webhook Signatures)
2. Use **Quick Reference Example #5** (Error Handling with Retry)
3. Build conversation flows with **Quick Reference Example #9**
4. Create a messaging profile in `best-practices.md`

**Key Concepts to Master:**
- Messaging profiles
- Webhook security
- Error handling patterns
- Message segmentation

**Reference Files:**
- Study `webhooks.md` for event types and security
- Review `best-practices.md` for production patterns
- Use `error-codes.md` for comprehensive error handling

### For Advanced Users

**Advanced Patterns:**
1. Implement bulk messaging from `best-practices.md` with queue system
2. Build IVR systems with Call Control API
3. Set up number pools for high-volume messaging
4. Implement comprehensive monitoring and alerting
5. Optimize message costs with encoding strategies

**Key Topics:**
- Message queue systems (Bull/Redis)
- Database-backed idempotency
- Structured logging (Winston)
- Metrics collection (Prometheus)
- Production deployment patterns

**Reference Files:**
- Deep dive into `best-practices.md` for all production patterns
- Study `error-codes.md` for comprehensive error handling
- Review `webhooks.md` for advanced webhook patterns

## API Essentials

### Base URL
```
https://api.telnyx.com/v2
```

### Authentication Header
```
Authorization: Bearer YOUR_API_KEY
```

### Environment Variables
```bash
# .env file
TELNYX_API_KEY=KEY019A080F468AAFD4AF4F6888D7795244_xxx
TELNYX_PUBLIC_KEY=your_public_key_for_webhook_validation
TELNYX_MESSAGING_PROFILE_ID=abc85f64-5717-4562-b3fc-2c9600000000
```

### Rate Limits
- Standard accounts: 10 requests/second per endpoint
- High-volume accounts: Contact Telnyx for increased limits
- Implement exponential backoff for 429 responses

### Common Response Structure
```json
{
  "data": {
    "id": "message-uuid",
    "type": "SMS",
    "from": { "phone_number": "+18445550001" },
    "to": [{ "phone_number": "+18665550001", "status": "queued" }],
    "text": "Hello!",
    "cost": { "amount": "0.0051", "currency": "USD" }
  }
}
```

## Quick Start Checklist

- [ ] Sign up for Telnyx account at https://telnyx.com/sign-up
- [ ] Generate API key in Mission Control Portal
- [ ] Set up environment variables
- [ ] Purchase a phone number for testing
- [ ] Send your first test SMS (Quick Reference #1)
- [ ] Set up webhook endpoint (use ngrok for local dev)
- [ ] Implement webhook handler (Quick Reference #3)
- [ ] Add webhook signature verification (Quick Reference #7)
- [ ] Test two-way messaging
- [ ] Add error handling (Quick Reference #5)
- [ ] Configure messaging profile for production

## Additional Resources

- **Telnyx Developer Portal**: https://developers.telnyx.com/
- **API Reference**: https://developers.telnyx.com/api/
- **Mission Control Portal**: https://portal.telnyx.com/
- **Status Page**: https://status.telnyx.com/
- **Support Portal**: https://support.telnyx.com/
- **Official SDKs**: Node.js, Python, Ruby, PHP, Java, C#, Go

## Common Patterns

### Pattern: Message with Tracking
```javascript
const tracker = new Map();

async function sendTrackedMessage(to, from, text) {
  const response = await sendSMS(to, from, text);
  tracker.set(response.data.data.id, {
    to, from, text,
    status: 'queued',
    sentAt: new Date()
  });
  return response;
}

// In webhook handler
app.post('/webhooks/telnyx', (req, res) => {
  const event = req.body.data;
  if (event.event_type === 'message.delivered') {
    const msg = tracker.get(event.payload.id);
    if (msg) msg.status = 'delivered';
  }
  res.status(200).send('OK');
});
```

### Pattern: Idempotent Webhook Processing
```javascript
const processedEvents = new Set();

async function processWebhook(event) {
  // Skip duplicates
  if (processedEvents.has(event.id)) {
    return;
  }
  processedEvents.add(event.id);

  // Process event...
}
```

### Pattern: Format to E.164
```javascript
function formatToE164(number, defaultCountryCode = '1') {
  let digits = number.replace(/\D/g, '');
  if (!digits.startsWith(defaultCountryCode)) {
    digits = defaultCountryCode + digits;
  }
  return '+' + digits;
}

// Examples
formatToE164('415-555-2671');      // +14155552671
formatToE164('(415) 555-2671');    // +14155552671
```

## Support and Troubleshooting

### Getting Help
1. Check `error-codes.md` for specific error messages
2. Review `best-practices.md` for common patterns
3. Visit https://status.telnyx.com/ for service status
4. Contact support through Mission Control Portal

### Common Issues
- **401 Unauthorized**: Check API key format (`Bearer YOUR_API_KEY`)
- **10001 Invalid phone number**: Ensure E.164 format (`+14155552671`)
- **429 Rate limit**: Implement rate limiting (Quick Reference #6)
- **Webhooks not received**: Verify URL is publicly accessible with valid SSL

### Debugging Tips
```javascript
// Enable request/response logging
axios.interceptors.request.use(request => {
  console.log('Request:', request.url, request.data);
  return request;
});

axios.interceptors.response.use(
  response => {
    console.log('Response:', response.status, response.data);
    return response;
  },
  error => {
    console.error('Error:', error.response?.data);
    return Promise.reject(error);
  }
);
```

