# Telnyx Fundamentals: Development — Full Documentation
> Complete page content for Development (Fundamentals section) of the Telnyx developer docs (https://developers.telnyx.com).
> This file: https://developers.telnyx.com/docs/development/llms-txt-full.md · Root index: https://developers.telnyx.com/llms.txt
##
### Development
> Source: https://developers.telnyx.com/docs/development.md
## Build with confidence
From authentication utilities to multi-platform SDKs, this section mirrors the
hands-on developer resources from our classic docs so you can build, test, and
ship with Telnyx even faster.
## What you’ll find here
Learn how to create and secure API keys, handle webhooks, and stay within
rate limits across every Telnyx service.
Dig into API fundamentals →
Official SDKs for Node.js, Python, PHP, Java, Ruby, and Go to simplify
backend integrations and speed up prototyping.
Browse SDKs →
Build voice and video experiences with JavaScript, React, iOS, and Android
SDKs plus detailed class references.
Explore WebRTC →
Level up your workflow with Postman collections, ngrok tunneling, and
Node-RED recipes for rapid testing.
Get the toolkit →
Troubleshoot with call detail records, WebRTC debugging steps, and logging
best practices.
Start debugging →
Step-by-step playbooks for migrating messaging, Call Control, and Twilio
workloads onto Telnyx.
Plan your migration →
## Working on AI agents?
Spin up local or remote MCP servers so your AI assistants can query Telnyx APIs
securely—check out the [MCP quickstarts](/docs/development/mcp/local-mcp).
## Need product-specific guides?
Looking for AI, Voice, or Messaging docs? Explore our product tabs above.
---
## Account setup
### Create Account
> Source: https://developers.telnyx.com/docs/account-setup/create-account.md
Before you can start using any Telnyx services, you'll need to create an account to access our APIs and Mission Control Portal.
## Account creation steps
Navigate to [telnyx.com/sign-up](https://telnyx.com/sign-up) to start the signup process.
Enter your contact information, company details, and a secure password. This ensures Telnyx can verify who you are.
Look for the confirmation email and click the verification link so we know you're the owner of the address you used.
Access the [Mission Control Portal](https://portal.telnyx.com) with your new credentials to finish onboarding and explore your dashboard.
New accounts come with free testing credits so you can explore the platform before adding payment methods.
## Need help?
If you encounter any issues during account creation:
- Review the [Account Setup FAQ](https://support.telnyx.com)
- Contact our support team through the Mission Control Portal
- Join the [Telnyx Slack community](https://joinslack.telnyx.com) for developer support
---
### Account Signup
> Source: https://developers.telnyx.com/docs/account-setup/signup.md
Every signup attempt is subjected to a battery of trust and safety checks. Among them, in no particular order, are the following:
- Domain age
- Domain reputation
- Host reputation
- IP reputation
- Signup origin
- reCAPTCHA verification
An attempt will be unsuccessful if **any** of the above fails.
Some attempts may also be subjected to additional requirements, including:
- Successfully validating a legitimate mobile number
- Successfully passing Know Your Customer (KYC) documentation verification
Telnyx constantly adjusts the logic, sequence, and thresholds to combat signup abuse and fraudulent usage of the platform.
---
### Account Levels Overview
> Source: https://developers.telnyx.com/docs/account-setup/levels-and-capabilities.md
A successful signup may be placed in one of the following frameworks (**but never both**):
- Level 1 / Level 2 account framework
- Pretrial-Trial-Paid-Verified-Enterprise (PTPVE) framework
An account is in the Level 1 / Level 2 framework when the [verification page](https://portal.telnyx.com/#/account/my-account/verifications) exists in the user's Mission Control Portal account.
The remainder of this account setup section is only relevant to an account in the PTPVE framework.
An account is in the PTPVE framework when the [Account Levels page](https://portal.telnyx.com/#/account/account-levels) exists in the user’s Mission Control Portal account.
The level of an account is an organizational attribute. If the account is a paid account, all organization members have the privileges and limits of a paid account.
For a holistic understanding of privileges and limits at each account level, consult the corresponding pages in this section, together with the following tables:
- V2 APIs
- S3 Compatible Storage APIs
---
### Pretrial Account
> Source: https://developers.telnyx.com/docs/account-setup/levels-and-capabilities/pretrial.md
## Testing credit
**USD $25** in AI credits is provided.
## Access
- Full access to AI Suite (AI Assistant, Inference, Cloud Storage) except otherwise specified below.
- Telnyx reserves the right to modify limitations without notification.
## Numbers
### Number searching
- Full number display limited to **USA local numbers** only.
- All other numbers will be shown redacted (e.g., +49351xxxxxxx).
- No access to other APIs or features in this category.
### Number reservation
- No access to APIs or features in this category.
### Number ordering
- Limited to **1 USA local number** per **pretrial account lifetime**.
- No access to global numbers.
- No port out is allowed on this number.
- This number will be reclaimed within 30 days of purchase if the account has not upgraded.
- No access to other APIs or features in this category.
### Number porting
- No access to APIs or features in this category.
### Bundles
- No access to APIs or features in this category.
## Messaging
- Limited to **1 messaging profile** at any one time.
- **Outbound:** Limited to long code sending, destination limited to verified number, and capped at **10 messages a day**.
- **Inbound:** Limited to receiving from the verified number.
- No access to other APIs or features in this category.
## Verify
- No access to APIs or features in this category.
## Voice
### General limits
- Limited to **1 TeXML Application** at any one time.
- Limited to **1 outbound voice profile** at any one time.
- **Outbound** limited to dialing only the verified phone number.
- **Inbound** limited to receiving from the verified phone number.
- Limited to **2 concurrent outbound calls**.
- Limited to a maximum of **10 minutes per call**.
### Programmable Voice
- All machine-generated voices are prepended with: "_This is an automated call generated on the Telnyx platform, please report any abuse to fraud@telnyx.com_".
- This applies to:
- `/v2/calls`
- `/v2/calls/:call_control_id/actions/transfer`
- `/v2/calls/:call_control_id/actions/gather_using_audio`
- `/v2/calls/:call_control_id/actions/gather_using_speak`
- `/v2/calls/:call_control_id/actions/playback_start`
- `/v2/calls/:call_control_id/actions/speak`
- `/v2/calls/:call_control_id/actions/gather_using_ai`
- `/v2/calls/:call_control_id/actions/ai_assistant_start`
- TeXML verb `Play`
- TeXML verb `Say`
- TeXML verb `AIGather`
- Limited to a maximum of **10 outbound calls a day**.
### Call Control Applications
- No access to APIs or features in this category.
### Microsoft Operator Connect
- No access to APIs or features in this category.
### Microsoft Direct Routing
- No access to APIs or features in this category.
### Zoom Phone Provider Exchange
- No access to APIs or features in this category.
## LRN / Number Lookup
- No access to APIs or features in this category.
## Cloud Storage
- Limited to non-public policy or ACL on buckets or objects.
- Limited to **5 minutes of TTL** on pre-signed URLs.
- Limited to the documented free tier of used capacity across all buckets and regions.
## Wireless
- No access to APIs or features in this category.
## Account features
### Organizations and sub-users
- No access to APIs or features in this category.
### ManagED Accounts
- No access to APIs or features in this category.
### Payment methods
- No access to APIs or features in this category. Credit is not required — AI credits are provided.
### Billing groups
- No access to APIs or features in this category.
### API keys
- Limited to **1 API key** at any one time.
- No access to other APIs or features in this category.
### DDoS mitigation
- No access to APIs or features in this category.
---
### Trial Account
> Source: https://developers.telnyx.com/docs/account-setup/levels-and-capabilities/trial.md
## Testing credit
**USD $5** in testing credit is provided.
## Access
- Full access except otherwise specified below.
- Telnyx reserves the right to modify limitations without notification.
## Numbers
### Verified numbers
- Limited to **1 verified number** at any one time.
- Limited to **10 changes** per **trial account lifetime**.
- Limited to **15 delivery attempts** regardless of conversion outcome per **trial account lifetime**.
### Number searching
- Full number display limited to **local numbers** of the account's country of origin.
- All other numbers will be shown redacted (e.g., +49351xxxxxxx).
- No access to other APIs or features in this category.
### Number reservation
- No access to APIs or features in this category.
### Number ordering
- Limited to **1 local number** of the account's country of origin per **trial account lifetime**.
- Successful number activation is subject to inventory availability, sufficient account balance, and local jurisdiction documentation rules.
- This number will be reclaimed within 30 days of purchase if the account has not upgraded.
- No port out is allowed on this number.
- No access to other APIs or features in this category.
### Number porting
- Limited to **50 portability check attempts** per **trial account lifetime**.
- No access to other APIs or features in this category.
- Users do not have proprietary rights to their trial telephone number, and Telnyx reserves the right to make reasonable changes to them with reasonable notice. Users cannot port out their trial number.
### Bundles
- No access to APIs or features in this category.
## Messaging
- Limited to **1 messaging profile** at any one time.
- **Outbound:** Limited to long code sending, destination limited to verified number, and capped at **100 messages a day**.
- **Inbound:** Limited to receiving from the verified number.
- No access to other APIs or features in this category.
## Verify
- Limited to **1 verified profile** at any one time.
- Only SMS is allowed.
- Destination limited to verified number.
- Limited to a max of **50 verifications a day**.
- No access to other APIs or features in this category.
## Voice
### General limits
- Limited to **1 instance per connection type** at any one time.
- Limited to **1 outbound voice profile** at any one time.
- **Outbound** limited to dialing only the verified phone number.
- **Inbound** limited to receiving from the verified phone number.
- Limited to **2 concurrent outbound calls** across all connection instances.
- Limited to a maximum of **10 minutes per call**.
### Programmable Voice
- All machine-generated voices are prepended with: “_This is an automated call generated on the Telnyx platform, please report any abuse to fraud@telnyx.com_”.
- This applies to:
- `/v2/calls`
- `/v2/calls/:call_control_id/actions/transfer`
- `/v2/calls/:call_control_id/actions/gather_using_audio`
- `/v2/calls/:call_control_id/actions/gather_using_speak`
- `/v2/calls/:call_control_id/actions/playback_start`
- `/v2/calls/:call_control_id/actions/speak`
- `/v2/calls/:call_control_id/actions/gather_using_ai`
- `/v2/calls/:call_control_id/actions/ai_assistant_start`
- TeXML verb `Play`
- TeXML verb `Say`
- TeXML verb `AIGather`
- Limited to a maximum of **100 outbound calls a day**.
- Limited to **10 outbound calls per hour**.
### Microsoft Operator Connect
- No access to APIs or features in this category.
### Microsoft Direct Routing
- No access to APIs or features in this category.
### Zoom Phone Provider Exchange
- No access to APIs or features in this category.
## LRN / Number Lookup
- No access to APIs or features in this category.
## Cloud Storage
- Limited to non-public policy or ACL on buckets or objects.
- Limited to **5 minutes of TTL** on pre-signed URLs.
- Limited to the documented free tier of used capacity across all buckets and regions.
## Wireless
- No access to physical SIM registration.
- No access to eSIM purchase.
## Account features
### Organizations and sub-users
- No access to APIs or features in this category.
### ManagED Accounts
- No access to APIs or features in this category.
### Payment methods
- Limited to credit cards.
### Billing groups
- No access to APIs or features in this category.
### API keys
- Limited to **1 API key** at any one time.
- No access to other APIs or features in this category.
### DDoS mitigation
- No access to APIs or features in this category.
---
### Using Your Trial Account
> Source: https://developers.telnyx.com/docs/account-setup/using-trial-account.md
Follow this process to make the most of your trial credit and stay within trial limitations.
A [verified number](https://portal.telnyx.com/#/numbers/verified-numbers) is essential to test Voice and Messaging. Use a mobile phone number that you control.
Keep in mind that trial accounts have limits on delivery attempts and the number of changes allowed. Once the allowance is depleted, [upgrade your account](/docs/account-setup/account-upgrade).
Search results show only local (to the signup origin) numbers in full +E164; other results appear partially redacted.
A successful purchase depends on inventory availability, sufficient account balance, and local jurisdiction [documentation rules](https://portal.telnyx.com/#/numbers/requirements). Only **one** phone number order is allowed during the trial, regardless of the outcome.
Use one of the following tutorials to place calls:
- [SIP Trunking](https://developers.telnyx.com/docs/voice/sip-trunking/get-started)
- [Programmable Voice](https://developers.telnyx.com/docs/voice/programmable-voice/get-started)
- [TeXML](https://developers.telnyx.com/docs/voice/programmable-voice/texml-setup)
Regardless of how the call is created, the destination is limited to the verified phone number from Step 1, and inbound calls must also originate from that number. Check [trial voice limits](/docs/account-setup/levels-and-capabilities/trial).
Use the [Send Message](https://developers.telnyx.com/docs/messaging/messages/send-message) tutorial to send SMS.
Outbound messages must target the verified phone number you configured, and inbound messages must also originate from that number. Check [trial messaging limits](/docs/account-setup/levels-and-capabilities/trial).
---
### Paid Account
> Source: https://developers.telnyx.com/docs/account-setup/levels-and-capabilities/paid.md
## Access
- Full access except otherwise specified below.
- Telnyx reserves the right to modify limitations without notification.
## Numbers
### Number searching
- No access to number blocks.
### Number ordering
- Limited to local numbers whose country code matches the account's country of origin.
### Number porting
- No access to LRN migration.
## Messaging
- No access to 10DLC.
- No access to Toll-Free verification.
- No access to hosted messaging.
## Voice
### General limits
- Limited set of outbound destination country codes.
- Limited to **5 concurrent outbound calls** across all connection types.
### Programmable Voice
- All machine-generated voices are prepended with: “_This is an automated call generated on the Telnyx platform, please report any abuse to fraud@telnyx.com_”.
- This applies to:
- `/v2/calls`
- `/v2/calls/:call_control_id/actions/transfer`
- `/v2/calls/:call_control_id/actions/gather_using_audio`
- `/v2/calls/:call_control_id/actions/gather_using_speak`
- `/v2/calls/:call_control_id/actions/playback_start`
- `/v2/calls/:call_control_id/actions/speak`
- `/v2/calls/:call_control_id/actions/gather_using_ai`
- `/v2/calls/:call_control_id/actions/ai_assistant_start`
- TeXML verb `Play`
- TeXML verb `Say`
- TeXML verb `AIGather`
- Limited to a maximum of **100 outbound calls a day**.
- Limited to **10 outbound calls per hour**.
## Cloud Storage
- Limited to non-public policy or ACL on buckets or objects.
- Limited to **5 minutes of TTL** on pre-signed URLs.
## Account features
### ManagED Accounts
- No access to APIs or features in this category.
### Payment methods
- Credit card
- PayPal
### DDoS mitigation
- No access to APIs or features in this category.
---
### Verified Account
> Source: https://developers.telnyx.com/docs/account-setup/levels-and-capabilities/verified.md
## Access
- Full access except otherwise specified below.
- Telnyx reserves the right to modify limitations without notification.
## Numbers
### Number searching
- No access to number blocks.
### Number ordering
- No access to number blocks.
### Number porting
- No access to LRN migration.
## Account features
### ManagED Accounts
- No access to APIs or features in this category.
### Payment methods
- Credit card
- PayPal
- BTC
### DDoS mitigation
- No access to APIs or features in this category.
Qualification by the Telnyx sales team is required to upgrade your account to the enterprise level to gain access to the above features. [Contact Telnyx](https://telnyx.com/contact-us) to start the process.
---
### Account Upgrade
> Source: https://developers.telnyx.com/docs/account-setup/account-upgrade.md
| Criteria to meet | Pretrial | Trial | Paid | Verified |
| --- | :---: | :---: | :---: | :---: |
| Verified email | X | X | X | X |
| Passed fraud review (LinkedIn/GitHub verification or AI agent eval) | | X | X | X |
| Verified mobile number | | | X | X |
| Made a payment with CC/Debit Card | | | X | X |
| Enabled 2FA for the account | | | X | X |
| Provided Service Address | | | X | X |
| Successfully passed KYC | | | | X |
| Successfully passed AI agent eval | | | | X |
Identify the desired account level and complete **all** [required actions](https://portal.telnyx.com/#/account/account-levels). For enterprise upgrades, qualification by the Telnyx sales team is required. [Contact Telnyx](https://telnyx.com/contact-us) to begin the process.
---
### Data Locality
> Source: https://developers.telnyx.com/docs/account-setup/data-locality.md
Data Locality lets you choose the geographic region where your Telnyx data is stored at rest.
---
## Available regions
| Region | Location | Default |
|:-------|:---------|:--------|
| US | United States | Yes |
| EU | Germany | No |
| APAC | Australia | No |
| Middle East | UAE | No |
---
## Covered data types
Data locality applies to the following data stored at rest:
- Call Detail Records (CDRs)
- Message Detail Records (MDRs)
- Conference records
- Forking CDRs
- Media Storage (recordings)
- Premium AMD
- Speech-to-Text
- Verify
- Video
- WhatsApp
- Wireless
---
## Selecting a region
1. Log in to the [Mission Control Portal](https://portal.telnyx.com).
2. Go to **Account settings** > **Profile**.
3. Scroll to **Data Storage Location** and select a country from the dropdown.
4. Click **Save Location**.
This setting can only be changed once and cannot be undone. After you save, Telnyx migrates your data to the new location. Some features may become temporarily unavailable during migration — the process can take a few minutes to several hours depending on your data size.
All existing accounts default to the US. If you do not change the setting, your data remains in the US.
---
## APIs fundamentals
### Create API Keys
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/create-api-keys.md
API keys are essential for authenticating your requests to any Telnyx API. This guide shows you how to create and manage your API keys through the Mission Control Portal.
## Creating Your API Key
1. In the Mission Control Portal, click on your name in the upper right corner, and click **API Keys**.
2. Click the **Create API Key** button.

3. In the Create API Key dialog, add a descriptive tag (e.g., "Voice API Development", "SMS Production", etc.) and choose your expiration settings.

4. Click **Create**.
## Important: Save Your API Key Securely
We'll show the full API key value only once at creation. If you lose the key, you'll need to generate a new one.
We recommend using a secure password manager or secrets vault once you've created it. We're doing this to reduce the risk of accidental key leaks and help keep your account secure. This approach aligns with our best-in-class security standards and helps prevent accidental key exposures.
## Storing Your API Key
**Best Practices:**
- Never commit API keys to version control (Git, SVN, etc.).
- Use environment variables in your applications.
- Rotate keys regularly for production applications.
- Use separate keys for development and production.
Example of setting an environment variable:
```bash
export TELNYX_API_KEY="YOUR_API_KEY"
```
## Using Your API Key
Once created, you can use your API key with any Telnyx service:
### REST API
```bash
curl -X GET \
--header "Authorization: Bearer YOUR_API_KEY" \
"https://api.telnyx.com/v2/endpoint"
```
### SDKs
```javascript
// Node.js
const telnyx = require('telnyx')('YOUR_API_KEY');
// Python
import telnyx
telnyx.api_key = "YOUR_API_KEY"
// Ruby
Telnyx.api_key = "YOUR_API_KEY"
```
---
### API Authentication
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/authentication.md
All Telnyx APIs use consistent authentication mechanisms to ensure secure access to your resources. This guide covers the universal authentication patterns used across Voice, Messaging, Cloud Storage, IoT, and all other Telnyx services.
## API Keys
### Overview
Telnyx uses API Keys as the primary authentication method across all services. Your API Keys carry significant privileges and provide access to all Telnyx resources associated with your account.
### Security Best Practices
- **Keep API Keys secure**: Never share API Keys in publicly accessible areas such as GitHub, client-side code, or logs
- **Use environment variables**: Store API Keys in environment variables or secure configuration files
- **Rotate keys regularly**: Periodically generate new API Keys and deactivate old ones
- **Use least privilege**: If available, use API Keys with minimal required permissions
### Managing API Keys
You can view and manage your API Keys in the Auth section of your [Mission Control portal](https://portal.telnyx.com).
## Authentication Methods
### Bearer Token Authentication
Most Telnyx APIs use Bearer token authentication in the Authorization header:
```bash
curl -X GET \
--header "Authorization: Bearer YOUR_API_KEY" \
"https://api.telnyx.com/v2/endpoint"
```
### SDK Authentication
When using Telnyx SDKs, authentication is typically configured once during initialization:
```javascript
// Node.js SDK
const telnyx = require('telnyx')('YOUR_API_KEY');
// Python SDK
import telnyx
telnyx.api_key = "YOUR_API_KEY"
// Ruby SDK
Telnyx.api_key = "YOUR_API_KEY"
```
## Common Authentication Patterns
### RESTful APIs
- **Voice API**: Bearer token in Authorization header
- **Messaging API**: Bearer token in Authorization header
- **Cloud Storage**: AWS Signature Version 4 or Bearer token
- **IoT APIs**: Bearer token in Authorization header
### Real-time Connections
- **WebRTC**: JWT tokens for client authentication
- **WebSocket connections**: Bearer token during connection establishment
## Error Handling
### Authentication Errors
Common authentication-related HTTP status codes:
- **401 Unauthorized**: Invalid or missing API Key
- **403 Forbidden**: Valid API Key but insufficient permissions
- **429 Too Many Requests**: Rate limit exceeded
### Debugging Authentication Issues
1. **Verify API Key format**: Ensure the key is correctly formatted and complete
2. **Check headers**: Confirm the Authorization header is properly set
3. **Validate permissions**: Ensure your API Key has the required permissions for the resource
4. **Test with curl**: Use curl to isolate authentication issues from SDK problems
## Environment-Specific Considerations
### Development vs Production
- Use separate API Keys for development and production environments
- Never use production API Keys in development or testing
- Consider using restricted API Keys for development
### Regional Considerations
Some Telnyx services may have regional API endpoints. Always check the specific service documentation for the correct base URL.
## Account Management
### Account Levels and Access
Account levels determine which APIs and features are available to you. For detailed information about account types, capabilities, and verification requirements, see [Account Levels and Capabilities](https://developers.telnyx.com/docs/account-setup/levels-and-capabilities).
## Next Steps
- **API Reliability & Retries** - Handle authentication failures gracefully
- **Webhook Security** - Secure your webhook endpoints
- **SDKs & Tools** - Language-specific authentication setup
---
### HTTP Patterns
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/request-response.md
Understanding common request and response patterns will help you build robust integrations across all Telnyx services. This guide covers the universal HTTP concepts that apply to Voice, Messaging, Cloud Storage, IoT, and all other Telnyx APIs.
## HTTP Methods
Telnyx APIs follow RESTful conventions using standard HTTP methods:
### **GET** - Retrieve Resources
Used to fetch information without making changes:
```bash
GET /v2/messaging_profiles
GET /v2/calls/{call_id}
GET /v2/storage/buckets
```
### **POST** - Create Resources
Used to create new resources or trigger actions:
```bash
POST /v2/calls # Make a phone call
POST /v2/messages # Send a message
POST /v2/storage/objects # Upload a file
```
### **PATCH** - Update Resources
Used to modify existing resources:
```bash
PATCH /v2/messaging_profiles/{id} # Update profile
PATCH /v2/phone_numbers/{id} # Update phone number settings
```
### **DELETE** - Remove Resources
Used to delete resources:
```bash
DELETE /v2/messaging_profiles/{id} # Delete messaging profile
DELETE /v2/telephony_credentials/{id} # Delete telephony credential
```
## Request Format
### Content-Type Headers
Most Telnyx APIs expect JSON payloads:
```bash
Content-Type: application/json
```
For file uploads or form data:
```bash
Content-Type: multipart/form-data
Content-Type: application/x-www-form-urlencoded
```
### Request Structure
```bash
curl -X POST \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"to": "+1234567890",
"from": "+0987654321",
"text": "Hello World"
}' \
"https://api.telnyx.com/v2/messages"
```
## Response Format
### Standard Response Structure
Most Telnyx APIs return JSON responses with consistent structure:
```json
{
"data": {
"id": "resource_id",
"record_type": "resource_type",
// ... resource properties
},
"meta": {
"page_number": 1,
"page_size": 20,
"total_pages": 5,
"total_results": 100
}
}
```
### Success Responses
- **200 OK**: Request successful, data returned
- **201 Created**: Resource successfully created
- **202 Accepted**: Request accepted, processing asynchronously
- **204 No Content**: Request successful, no data to return
### Error Responses
Error responses include details to help troubleshoot issues:
```json
{
"errors": [
{
"code": "10001",
"title": "Invalid parameter",
"detail": "The 'to' field is required",
"source": {
"pointer": "/data/attributes/to"
}
}
]
}
```
### Telnyx API Error Codes
For a comprehensive list of all Telnyx-specific error codes and their meanings, see the [API Error Codes reference](/docs/development/api-fundamentals/api-errors). This resource provides detailed explanations for each error code to help you troubleshoot and handle API errors effectively.
Common error patterns include:
- **10xxx codes**: Parameter validation errors
- **20xxx codes**: Authentication and authorization errors
- **30xxx codes**: Resource not found or unavailable errors
- **40xxx codes**: Rate limiting and quota errors
- **50xxx codes**: Server-side errors
## HTTP Status Codes
### Client Errors (4xx)
- **400 Bad Request**: Invalid request format or parameters
- **401 Unauthorized**: Authentication failed
- **403 Forbidden**: Authentication succeeded but access denied
- **404 Not Found**: Resource doesn't exist
- **422 Unprocessable Entity**: Valid request format but logical errors
- **429 Too Many Requests**: Rate limit exceeded
### Server Errors (5xx)
- **500 Internal Server Error**: Unexpected server error
- **502 Bad Gateway**: Upstream service error
- **503 Service Unavailable**: Service temporarily unavailable
- **504 Gateway Timeout**: Request timeout
## Common Headers
### Request Headers
```bash
Authorization: Bearer YOUR_API_KEY # Authentication
Content-Type: application/json # Request format
Accept: application/json # Expected response format
User-Agent: YourApp/1.0 # Client identification
```
### Response Headers
```bash
Content-Type: application/json # Response format
X-RateLimit-Limit: 100 # Rate limit maximum
X-RateLimit-Remaining: 75 # Remaining requests
X-RateLimit-Reset: 1640995200 # Rate limit reset time
```
## Pagination
For endpoints that return lists, Telnyx uses consistent pagination:
### Request Parameters
```bash
GET /v2/messages?page[number]=2&page[size]=50
```
### Response Metadata
```json
{
"data": [...],
"meta": {
"page_number": 2,
"page_size": 50,
"total_pages": 10,
"total_results": 500
}
}
```
## Filtering and Sorting
### Common Filter Patterns
```bash
# Filter by date range
GET /v2/messages?filter[created_at][gte]=2023-01-01
# Filter by status
GET /v2/calls?filter[status]=completed
# Sort results
GET /v2/messages?sort=created_at
GET /v2/calls?sort=-created_at # Descending order
```
## Best Practices
### Request Optimization
- **Use appropriate HTTP methods**: Don't use POST for retrieving data
- **Include relevant headers**: Specify Content-Type and Accept headers
- **Validate input**: Check parameters before sending requests
- **Handle timeouts**: Set appropriate timeout values
### Response Handling
- **Check status codes**: Don't assume all responses are successful
- **Parse error messages**: Use error details for troubleshooting
- **Handle edge cases**: Account for empty results and partial failures
- **Log appropriately**: Log errors but avoid logging sensitive data
## Next Steps
- **API Reliability & Retries** - Handle failed requests
- **Webhook Fundamentals** - Receive asynchronous notifications
- **API Glossary** - Reference for API terminology
---
### API error codes
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/api-errors.md
This page lists the general Telnyx API error codes. Product-specific delivery, protocol, SDK, and provider errors are maintained in their product references and combined with this table in the unified catalog.
- [Unified machine-readable error catalog](https://developers.telnyx.com/data/api-errors.json): normalized entries with product scope, source provenance, and authored remediation metadata.
- [Catalog source registry](https://developers.telnyx.com/data/error-catalog-sources.json): versioned inventory of the maintained public tables included by the generator.
## Product-specific references
- [10DLC troubleshooting](/docs/messaging/10dlc/troubleshooting)
- [Call Control webhook errors](/docs/voice/programmable-voice/voice-api-webhooks)
- [Edge Compute Stateful Actor errors](/docs/edge-compute/stateful-actors/api-reference/errors)
- [Email API errors](/docs/messaging/email/error-codes)
- [Messaging delivery errors](/docs/messaging/messages/error-codes)
- [SIP response codes](/docs/voice/sip-trunking/troubleshooting/response-codes)
- [Speech-to-Text WebSocket errors](/docs/voice/stt/websocket-streaming/errors)
- [Text-to-Speech WebSocket errors](/docs/voice/tts/websocket-streaming/errors)
- [Toll-Free Verification troubleshooting](/docs/messaging/toll-free-verification/troubleshooting)
- [Voice Design Lab errors](/docs/voice/voice-design-lab/clone-voice/errors)
- [WebRTC JavaScript SDK error handling](/docs/development/webrtc/js-sdk/how-to/error-handling)
- [WhatsApp template errors](/docs/messaging/whatsapp/manage-templates)
- [Wireless API errors](/docs/iot-sim/api-errors)
## General API error codes
| Code | Title | Detail |
| --- | --- | --- |
| 10001 | Inactive phone number | The phone number is inactive. |
| 10002 | Invalid phone number | The phone number is invalid. |
| 10003 | Invalid URL | The URL provided was invalid, malformed, or too long. URLs can be a maximum of 2000 characters. |
| 10004 | Missing required parameter | A required parameter was missing. |
| 10005 | Resource not found | The requested resource or URL could not be found. |
| 10006 | Invalid ID | The resource ID provided was invalid. |
| 10007 | Unexpected error | An unexpected error occured. |
| 10008 | Request timeout | The request timed out. |
| 10009 | Authentication failed | The required authentication headers were either invalid or not included in the request. |
| 10010 | Authorization failed | You do not have permission to perform the requested action on the specified resource or resources. |
| 10011 | Too many requests | You have exceeded the maximum number of allowed requests. |
| 10012 | Duplicate resource | Resource is a duplicate. |
| 10013 | Missing association | One of the associated fields does not exist. |
| 10014 | Unsupported Media Type | The request failed because the server does not support the media type. |
| 10015 | Bad Request | The request failed because it was not well-formed. |
| 10016 | Phone number must be in +E.164 format | The specified phone number parameter must be in +E.164 format. |
| 10017 | Associated resource does not exist | The requested parameter is invalid as the associated resource does not exist. |
| 10018 | Invalid sort direction | The 'sort_direction' parameter must have a value of either 'asc' or 'desc'. |
| 10019 | Invalid email address | The 'email' parameter is not a valid email address. |
| 10020 | Invalid resource type | The requested parameter must be of type 'string' |
| 10021 | Resource in use | The resource can not be removed as it is still in use. |
| 10022 | One or more invalid IDs | One or more of the IDs provided were invalid. |
| 10023 | Invalid JSON | The supplied JSON is invalid. |
| 10024 | Unsupported Content-Type | Must encode request as 'application/x-www-form-urlencoded' or 'application/json' |
| 10025 | String length out of range | The string length provided for the indicated field was outside the allowed range. The field must be between {min} and {max} characters long, but was {actual}. |
| 10026 | Invalid parameter type | The parameter must be of type {expected_type}, but received type {received_type} |
| 10027 | Unprocessable Entity | The server understood the syntax of the request but was unable to process the instructions. |
| 10028 | Character encoding error | The request body was not able to be decoded. |
| 10029 | Expected JSON Content-Type | Must encode request as 'application/json' |
| 10030 | Method not allowed | The URL is valid, but the method is not allowed. |
| 10031 | Invalid request filter | The request filter filter[{filter}] is invalid. |
| 10032 | Invalid enumerated value | The value must be one of {enumerated_values} |
| 10033 | Value outside of range | The value is outside of allowed range {min_allow} to {max_allow} |
| 10034 | Expected URL-encoded form Content-Type | Must encode request as 'application/x-www-form-urlencoded' |
| 10035 | Resource locked | The resource has been locked. Contact Telnyx support. |
| 10036 | Resource is being processed | This resource is in ongoing processing and it can't be interacted with. Please, wait for its operation to finish and retry later. |
| 10037 | Service unavailable | Service is unavailable. |
| 10038 | Feature not permitted | This feature is not permitted at this account level. Refer to https://telnyx.com/upgrade. |
| 10039 | Feature limited | A limit for this feature has been reached at this account level. See https://telnyx.com/upgrade for options. |
| 10700 | Invalid caller data | The CNAM caller data provided is invalid. |
| 20000 | Invalid resource groups | The resource groups provided are invalid. |
| 20001 | Invalid API Key secret | The secret provided is invalid. |
| 20002 | API Key revoked | The API Key provided is not active. |
| 20003 | API Key forbidden | The API Key provided is forbidden. |
| 20004 | Invalid permission groups | The permission groups provided are invalid. |
| 20005 | Invalid user | The user provided is invalid. |
| 20006 | Expired access token | The access token provided is expired. |
| 20007 | Invalid permission groups | The permission groups provided must be a subset of the API Key's. |
| 20008 | Invalid API Key | The API Key provided is invalid. |
| 20009 | Invalid user | The user provided does not exist. |
| 20010 | Invalid invitation | The invitation provided does not exist. |
| 20011 | API Key in use | The API Key can not be revoked while assigned to a portal user. |
| 20012 | Account inactive | The request cannot be fulfilled because your account has been deactivated. It may be out of funds. |
| 20013 | Account blocked | Your account has been blocked. Please contact Telnyx support. |
| 20014 | Account unverified | You have not completed the verifications required to perform this action. Check the 'verifications' tab under 'account' on the portal for more information. |
| 20015 | Feature not enabled | The {feature} feature is not enabled on your account. |
| 20016 | Account not level 1 verified | Level 1 account verification is required to perform this action. Check the 'verifications' tab under 'account' on the portal for more information. |
| 20017 | Account not level 2 verified | Level 2 account verification is required to perform this action. Check the 'verifications' tab under 'account' on the portal for more information. |
| 20100 | Insufficient Funds | You do not have enough funds to perform this action. |
| 20200 | Invalid address | The address provided is invalid. |
| 20201 | Invalid country code | The country code provided is invalid. |
| 20202 | Invalid locality | The locality provided is invalid. |
| 20203 | Invalid neighborhood | The neighborhood provided is invalid. |
| 20204 | Invalid administrative area | The administrative area provided is invalid. |
| 20205 | Invalid postal code | The postal code provided is invalid. |
| 20206 | Invalid borough | The borough provided is invalid. |
| 20207 | Invalid street address | The street address provided is invalid. |
| 20208 | Invalid street address house number | The street address house number provided is invalid. |
| 20209 | Invalid extended address | The extended address provided is invalid. |
| 40001 | Not routable | The destination number is either a landline or a non-routable wireless number. |
| 40002 | Blocked as spam - temporary | The message was flagged by a SPAM filter and was not delivered. This is a temporary condition. |
| 40003 | Blocked as spam - permanent | The message was flagged by a SPAM filter and was not delivered. The originating phone number is permanently blocked. |
| 40004 | Rejected by destination | The recipient server is rejecting the message for an unknown reason. |
| 40005 | Message expired during transmission | The message expired before it could be fully delivered to the recipient. |
| 40006 | Recipient server unavailable | The recipient server is unavailable or not responding. |
| 40007 | Loop detected | Infinite loop detected. |
| 40008 | Undeliverable | The recipient carrier did not accept the message. |
| 40009 | Invalid message body | The message body was invalid. |
| 40010 | Not 10DLC registered | The sending number is not 10DLC-registered but is required to be by the carrier. |
| 40011 | Too many requests | Exceeded upstream rate limit. As a result the message was flagged by a SPAM filter and was not delivered. This is a temporary condition. |
| 40012 | Invalid messaging destination number | The destination phone number was deemed invalid by the carrier. |
| 40013 | Invalid messaging source number | The source phone number was deemed invalid by the carrier. |
| 40014 | Message expired in queue | The message was not sent by Telnyx because its validity period expired. |
| 40015 | Blocked as spam - internal | The message was flagged by an internal Telnyx SPAM filter. |
| 40016 | T-Mobile 10DLC Sending Limit Reached | You have exceeded T-Mobile's allotted throughput limits for the campaign associated to this phone number |
| 40017 | AT&T 10DLC Spam Message Rejected | AT&T has rejected your message for spam on the 10DLC route |
| 40018 | AT&T 10DLC Sending Limit Reached | You have exceeded AT&T's allotted throughput limits for the campaign associated to this phone number |
| 40019 | AT&T 10DLC Invalid Tag Data | AT&T has rejected your message because the tagging information is incorrect |
| 40020 | Blocked as potentially artificial inflation of traffic | Sending of 2FA traffic has been blocked for 24 hours. |
| 40100 | Number not messaging enabled. | The number is not currently messaging enabled. |
| 40150 | Toll free number not in registry | Messaging cannot be enabled for this number because the number is not in the voice registry. |
| 40151 | Message enablement pending with other provider | Messaging is in the process of being enabled with another messaging provider. |
| 40152 | Invalid OSR parameter | One of the parameters sent to the OSR was missing or invalid. |
| 40153 | Cannot access OSR | Telnyx is not authorized to access the OSR. |
| 40154 | Unauthorized NNID | Telnyx is not authorized to use this NNID. |
| 40155 | LOA required | An LOA is required to text message enable this number. |
| 40156 | Unauthorized property name/value | Telnyx is not authorized to provision this property name or property value. |
| 40157 | Temporarily blocked | Telnyx is temporarily unable to make changes to the OSR. |
| 40158 | Delete failed | The record was not found or the NNID was invalid so it could not be deleted. |
| 40159 | Unknown OSR error | An error occurred while updating the OSR. |
| 40300 | Blocked due to STOP message | Messages cannot be sent from {src} to {dst} due to an existing block rule. |
| 40301 | Unsupported message type for the 'to' address | Sending messages from {src} to {dst} is currently unsupported. |
| 40302 | Message too large | The SMS message would be divided into {parts} parts. The maximum is {max_parts}. |
| 40303 | Message not found | The message with ID {id} was not found. |
| 40304 | Invalid combination of message content arguments | The message must contain exclusively 'body' for SMS, or 'subject' and/or 'media_urls' for MMS |
| 40305 | Invalid 'from' address | The 'from' address should be string containing a valid phone number or alphanumeric sender ID associated with the sending messaging profile. |
| 40306 | Alpha sender not configured | The messaging profile doesn't have an associated alphanumeric sender ID. |
| 40307 | Alpha sender mismatch | The specified alphanumeric sender ID {provided_sender} does not match the one configured on the profile {expected_sender} |
| 40308 | Invalid 'from' address for MMS | MMS can only be sent from US long code numbers and MMS-configured short codes |
| 40309 | Invalid destination region | The region {region} for the destination {dst} is not included in the messaging profile's whitelisted destinations. |
| 40310 | Invalid 'to' address | The 'to' address should be a single valid number. |
| 40311 | Invalid messaging profile secret | The provided X-Profile-Secret header was invalid. |
| 40312 | Messaging profile is disabled | The specified messaging profile {id} is disabled. |
| 40313 | Missing messaging profile secret | The X-Profile-Secret header is missing. |
| 40314 | Messaging disabled on account | Messaging has been disabled on your account. Contact Telnyx support. |
| 40315 | Unhealthy 'from' address | Sending number {src} (with success rate {success} and spam rejection rate {spam}) did not pass the health check. |
| 40316 | No content provided for message | The message has no content. Either 'text' and/or 'media_urls' must be provided in the request. |
| 40317 | Invalid MMS content | MMS can only contain up to 10 items (URLs provided) and the total size must be less than 1 MB. |
| 40318 | Message queue full | Message queue is full. Wait before resending. |
| 40319 | Incompatible message type for the 'to' address | Sending messages from {src} to {dst} is not possible. |
| 40320 | Temporarily unusable 'from' address | The sending number {src} is in a temporarily unusable or pending state. |
| 40321 | No usable numbers on messaging profile | Number Pool is not enabled, or it is unable to select a usable number on the messaging profile. |
| 40322 | Blocked due to content | Message contains invalid content. |
| 40323 | Messaging activation failed | Could not enable messaging on the number. |
| 40324 | Messaging product type change failed | Could not change product types for the number. |
| 40325 | Invalid alphanumeric sender ID | The specified alphanumeric sender ID value is invalid. |
| 40326 | Cannot assign alphanumeric sender ID | The alphanumeric sender ID could not be assigned to the messaging profile. |
| 40327 | Invalid Domain | The domain provided is not listed as a valid domain to be used with URL Shortener |
| 40328 | SMS exceeds recommended size | The SMS message would be divided into {parts} parts. Messages over {max_parts} should be sent by MMS or by adding auto_detect=False. |
| 40329 | Tollfree number is not verified | Try verifying the number if you haven't already; otherwise double check that verification succeeded. |
| 40330 | Tollfree number is not provisioned | This TFN is not yet fully provisioned for messaging. |
| 40331 | Missing whitelisted destinations | Messaging profile is missing whitelisted destinations. |
| 40332 | Brand cannot be deleted | Brand cannot be deleted due to an associated active campaign. |
| 40333 | Messaging profile spend limit reached | Request refused because this would incur cost above the spend limit configured on the messaging profile. |
| 41000 | WhatsApp Error | {code} - {title} |
| 50000 | VRF still deployed | The VRF can not be removed as it is still deployed to one or more sites |
| 50001 | VRF not deployed | The VRF is not deployed at this site |
| 50002 | VRF already deployed | The VRF is already deployed at this site |
| 50003 | Invalid IP address | This is not a valid IP address |
| 50004 | Private IP address not permitted | Private IP addresses are not permitted |
| 50005 | Invalid CIDR block | This is not a valid CIDR block |
| 50006 | Private CIDR block not permitted | Private CIDR blocks are not permitted |
| 50007 | CIDR block too large | CIDR blocks are limited to /{prefixlen} and higher |
| 50008 | Can not delete IP from source | Can not delete IP from source {source} |
| 55001 | Credential expired, can not create token. | The credential used to create the token has expired. |
| 65001 | Invalid Room ID | The provided room_id was not valid. |
| 70000 | Consumption reached data limit | The consumption reached the defined data limit. Please, update the SIM card group data limit. |
| 70001 | There aren't enough available SIM cards | Insufficient inventory to satisfy order request. |
| 70002 | Invalid data format | The provided data attribute was invalid. |
| 70003 | Mobile operators' preferences priorities are out of sequence | The mobile operators' preferences priorities should be in an ascending order starting by 0. |
| 70004 | OTA update in progress | SIM card network preferences can't be defined when a previous OTA update is still in progress. |
| 70005 | Could not delete SIM card group | The SIM card group associated with the provided ID can not be deleted because there are SIM cards associated with the SIM card group. |
| 70006 | Could not delete default SIM card group | The SIM card group associated with the provided ID can not be deleted because it is the default SIM card group on your account. |
| 70007 | SIM card doesn't have a SIM card group | A SIM card cannot be enabled unless it's associated with a SIM card group. |
| 70008 | Public IPs are unavailable at this time | There aren't any public IPs available at this time. Please contact Telnyx support for more information. |
| 75000 | Webhook delivery error | The webhook was not successful |
| 75001 | Could not resolve name | Unable to resolve the webhook URL domain name |
| 75002 | Could not connect to host | Could not connect to the webhook host |
| 75003 | Certificate misconfiguration | Webhook host certificate could not be verified |
| 75004 | Expired certificate | The webhook host certificate has expired |
| 75005 | Certificate name mismatch | The domain name on the certificate does not match the domain in the URL |
| 75006 | Untrusted certificate root | The certificate is not signed by a trusted authority |
| 75299 | Webhook host returned a non-200 HTTP 2XX | The server returned an HTTP 2XX code, but was not the expected HTTP 200 |
| 75300 | Webhook host returned HTTP 3XX | The server returned an HTTP 3XX redirect |
| 75400 | Webhook host returned HTTP 400 | The server returned an HTTP 400 |
| 75404 | Webhook host returned HTTP 404 | The server returned an HTTP 404 |
| 75499 | Webhook host returned HTTP 4XX | The server returned an HTTP 4XX error |
| 75500 | Webhook host returned HTTP 500 | The server returned an HTTP 500 |
| 75599 | Webhook host returned HTTP 5XX | The server returned an HTTP 5XX error |
| 80000 | Wrong account | One or more numbers you are attempting to port do not belong to the specified account. |
| 80001 | Inactive number | One or more numbers you are attempting to port are not active on the account. Only active numbers may be ported. |
| 80002 | Wrong provider | Telnyx is not the service provider for one or more of the numbers you are attempting to port. |
| 80003 | Pending order | One or more numbers are already part of another port request. |
| 80004 | Invalid desired due date | The desired due date is not within the allowable window. Please review the porting guidelines. |
| 80005 | Invalid passcode or pin | The passcode or PIN provided does not match what has been assigned to the number. |
| 80006 | Invalid PON | The Purchase Order Number (PON) provided is invalid. It must be between 3 and 20 characters and may not contain special characters. |
| 80007 | FOC expired | The firm order committment has expired since the number was not ported on the agreed upon due date. |
| 80008 | Missing LOA | A valid LOA (Letter of Authorization) is required to port numbers. |
| 80009 | Illegible LOA | The LOA (Letter of Authorization) provided was illegible or unable to be viewed. |
| 80010 | Expired LOA | The LOA (Letter of Authorization) provided has expired and is no longer valid. |
| 80011 | Invalid SPID | The service provider ID (SPID) provided was not recognized. |
| 80012 | Unsuported carrier | The functionality requested is not supported with the specified carrier. |
| 80013 | Invalid country | Automated porting is only supported in the US and Canada. |
| 80014 | Service address mismatch | The service address provided does not match the address on the account. |
| 80015 | Stranded phone numbers | The BTN/ATN on the account is being ported out which would leave stranded any remaining phone numbers. |
| 80016 | No CSR data available | A CSR could not be retrieved because the data submitted did not match closely enough with the data on file with the carrier. |
| 80017 | Invalid service provider type | The 'service_provider_type' parameter must be one of either 'Telnyx' or 'Peerless'. |
| 80018 | Invalid FOC date | The 'foc_date' parameter must be an ISO8601 datetime selected from the available FOC dates. |
| 80019 | Invalid service provider ID | The 'service_provider_id' parameter must be the ID of an existing service provider. |
| 80020 | Invalid subscription status | The 'subscription_status' parameter is required and must have a value of 'pending', 'concurred', 'timer_expired', 'conflict', 'activated', 'cancel_pending', 'cancelled', 'disconnect_pending', 'disconnected' or 'failed' |
| 80021 | Invalid porting option | The 'porting_option' parameter is required and must have a value of 'full' or 'partial'. |
| 80022 | Invalid document type | The 'document_type' parameter must have value of 'loa', 'csr', 'invoice' or 'other'. |
| 80023 | Invalid value for rate centers | The 'rate_centers' parameter must be a list of valid rate centers. |
| 80024 | Record could not be deleted | The sub_request could not be deleted as it has associated phone_numbers. |
| 80100 | Subscription version not created | The new service provider did not create an NPAC subscription version. |
| 80101 | Subscription version does not match | The new service provider created an NPAC subscription version that does not match the record Telnyx created. |
| 80200 | Duplicate phone numbers found | Duplicate phone numbers were found in the request. |
| 80201 | Phone number limit exceeded | Too many phone numbers were specified for an LSR preorder. |
| 80400 | Invalid credentials | The Port PS account credentials were invalid. |
| 80401 | Too many phone numbers | There is a maximum of 1000 lookups per request. |
| 85000 | Must search phone number via search API first | You must search for the number through our API before attempting to purchase. |
| 85001 | Phone numbers not available | The numbers you are trying to order are no longer available for purchase. |
| 85002 | Phone numbers update not allowed on this order | You are trying to update a number that is not in this order. |
| 85003 | Regulatory requirements already satisfied | Regulatory requirements cannot be updated once all have been satisfied. |
| 85004 | Invalid connection id provided | The connection id provided is invalid. |
| 85005 | Invalid messaging profile id provided | The messaging profile id provided is invalid. |
| 85006 | The phone number is already reserved | The phone number {number} is already reserved. |
| 85007 | Reservation limit exceeded | You have too many active phone number reservations. |
| 85008 | Reservation extension limit exceeded | The reservation has reached its limit of allowed extensions. |
| 90000 | Invalid value for format | Format must be of type 'string' with a value of either 'mp3' or 'wav'. |
| 90001 | Invalid value for channels | Channels must be a 'string' with a value of either 'single' or 'dual'. |
| 90002 | Invalid value for timeout | The 'timeout' parameter must be an 'integer' with a minimum and a maximum value accepted by command |
| 90003 | Invalid value for inter_digit_timeout | The 'inter_digit_timeout' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 120000. |
| 90004 | Invalid value for min | The 'min' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90005 | Invalid value for max | The 'max' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90006 | Invalid value for tries | The 'tries' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90007 | Invalid value for terminating_digit | The 'terminating_digit' parameter must be a 'string' with a value of 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, or #. |
| 90008 | Invalid value for valid_digits | The 'valid_digits' parameter must be a 'string' with a value of 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, or #. |
| 90009 | Invalid value for loop | The 'loop' parameter must either be 'infinity' or an 'integer' with a minimum value of 1 and a maximum value of 100. |
| 90010 | Invalid value for payload | The 'payload' parameter should contain between 1 and 5000 characters. |
| 90011 | Invalid value for payload_type | The 'payload_type' parameter must be of type 'string' with a value of either text or ssml. |
| 90012 | Invalid value for voice | The 'voice' parameter must be 'female' or 'male' when using the en-US language. |
| 90013 | Invalid value for language | The 'language' parameter must be of type 'string' with a value of either de-DE, en-AU, en-GB, en-US, es-ES, fr-CA, fr-FR, it-IT, ja-JP, ko-KR, nl-NL, pt-BR, sv-SE or tr-TR. |
| 90014 | Invalid value for digits | The 'digits' parameter must be a 'string' made of a combination of either 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, w, W, * or #. |
| 90015 | Invalid Call Control ID | The provided call_control_id was not valid. |
| 90016 | Invalid value for stop | The 'stop' parameter must be a 'string' with a value of 'all', 'current' or 'overlay'. |
| 90017 | Invalid value for client_state | The 'client_state' parameter must be a valid base64 string. |
| 90018 | Call has already ended | This call is no longer active and can't receive commands. |
| 90019 | Conference has already ended | This conference is no longer active and can't receive commands. |
| 90020 | Call recording triggered before audio started | Call recording cannot be started until audio has commenced on the call. |
| 90021 | Invalid value for duration | The 'duration' parameter must be an 'integer' with a minimum value of 100 and a maximum value of 500. |
| 90022 | Invalid value for minimum_digits | The 'minimum_digits' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90023 | Invalid value for maximum_digits | The 'maximum_digits' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90024 | Invalid value for maximum_tries | The 'maximum_tries' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 128. |
| 90025 | Invalid value for timeout_millis | The 'timeout_millis' parameter must be an 'integer' with a minimum and a maximum value accepted by command |
| 90026 | Invalid value for inter_digit_timeout_millis | The 'inter_digit_timeout_millis' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 120000. |
| 90027 | Invalid value for duration_millis | The 'duration_millis' parameter must be an 'integer' with a minimum value of 100 and a maximum value of 500. |
| 90028 | Invalid value for timeout_secs | The 'timeout_secs' parameter must be an 'integer' with a minimum and a maximum value accepted by command |
| 90029 | Invalid value for time_limit_secs | The 'time_limit_secs' parameter must be an 'integer' with a minimum value of 60 and a maximum value of 14,000. |
| 90030 | Invalid value for service_level | The 'service_level' parameter must be of type 'string' with a value of either 'basic' or 'premium'. |
| 90031 | Call is not currently forked | Can't stop forking, because the call isn't currently forked. |
| 90032 | Too many conference participants | The participant is unable to join because the maximum number of participants ({num}) has been reached. |
| 90033 | Conference has no active participants | This conference does not have any active participants. |
| 90034 | Call has not been answered yet | This call can't receive this command because it has not been answered yet. |
| 90035 | Call not in queue | This call can't receive this command because it has not been put in any queue yet. |
| 90036 | Queue full | The queue is full and can't accept more calls. |
| 90037 | Queue max_size cannot be modified | Queue exists and max_size cannot be modified. |
| 90038 | Call already in queue | Call can't be added to a queue it's already in. |
| 90040 | Downloading audio file failed | Provided audio file couldn't be downloaded due to a timeout. |
| 90041 | User termination channels limit exceeded | The limit of simultaneous termination channels configured to your user has been reached. |
| 90042 | Outbound voice profile channels limit exceeded | The limit of simultaneous channels configured to the outbound voice profile associated to this connection has been reached. |
| 90043 | Connection outbound channels limit exceeded | The limit of simultaneous outbound channels configured to this call control connection has been reached. |
| 90044 | Conference join not allowed | Participant must not join the same conference twice. |
| 90045 | Media Streaming is used. | This command can't be issued when media streaming is used. |
| 90046 | Media Streaming Failed. | The media streaming failed to start. |
| 90048 | Media Streaming is not used. | This command can only be issued when media streaming is used. |
| 90049 | Invalid value for record_timeout_secs | The 'record_timeout_secs' parameter must be an 'integer' with a minimum value of 0. |
| 90053 | Call recording triggered with 'timeout_secs' while transcribing | Call recording can not be started with 'timeout_secs' while the call is being transcribed. |
| 90054 | Call Transcription is already in progress | Call Transcription can not be started more than once. |
| 90055 | Call transcription can not be stopped | Call transcription can not be stopped while there is a recording with 'timeout_secs' in progress. |
| 90056 | Invalid value for initial_timeout_millis | The 'initial_timeout_millis' parameter must be an 'integer' with a minimum value of 1 and a maximum value of 120000. |
| 90057 | Invalid call control event type for webhook_urls | The webhook_urls json keys must be valid call control event types. |
| 90058 | Invalid conference_id | The conference does not exist. |
| 90059 | Invalid value for recording_track | The 'recording_track' parameter must be a 'string' with a value of either 'inbound', 'outbound' or 'both'. |
| 90080 | Cannot issue a command on fax in the current state. | This command can only be issued when a fax is in either queued, media.processed or sending state. |
| 90081 | Cannot issue command for inbound fax. | This command can only be issued for outbound fax. |
| 90100 | Notification key is invalid | The notification key provided is invalid. |
| 90101 | Notification context is invalid | The required notification context was either invalid or not included in the request. |
| 90102 | Command is invalid | Call answer command cannot be issued for outbound calls. |
| 100001 | Invalid Dialogflow API | The value should be either 'es' or 'cx' |
---
### Rate Limiting
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/reliability/rate-limiting.md
In order to protect our services, we employ the use of [rate limits](https://en.wikipedia.org/wiki/Rate_limiting) on the majority of `api.telnyx.com` endpoints. These limits are typically static, but are subject to change based on usage and may be adjusted to align with changes in capacity.
For this reason, we include headers in our API responses that should be parsed and respected by your application. These headers aim to help you understand your current consumption rate and self-diagnose or prevent potential throttling issues.
## Rate Limit Headers
| Term | Description |
| --------------------- | -------------------------------------------------------------------------------- |
| x-ratelimit-limit | Displays the applicable rate limits for the current request |
| x-ratelimit-remaining | Indicates how many requests a user can still make within the current time window |
| x-ratelimit-reset | Shows the time in seconds until the rate limit resets |
When the rate limit is exceeded, responses with status code 429 will be returned,
indicating that you have exhausted the number of requests allowed in the current
window.
## Rate Limit Response
### HTTP Status Code
The status code of rate limit responses is [429](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429).
### Response Body
```json
{
"errors": [
{
"code": "10011",
"title": "Too many requests",
"detail": "You have exceeded the maximum number of allowed requests."
}
]
}
```
## Handling Rate Limits
### Best Practices
1. **Monitor Headers**: Always check the rate limit headers in API responses
2. **Implement Backoff**: Use exponential backoff when receiving 429 responses
3. **Cache Results**: Cache API responses when possible to reduce request frequency
4. **Distribute Load**: Spread requests across multiple time windows
### Over Your Rate Limit?
Contact support@telnyx.com if you find you are exceeding the rate limit.
## Product-Specific Rate Limits
Different Telnyx services may have different rate limiting strategies:
- **Messaging**: See [Rate Limiting](/docs/messaging/messages/rate-limiting) and [Message Encoding](/docs/messaging/messages/message-encoding) for messaging-specific limits
- **10DLC**: See [10DLC rate limits](/docs/messaging/10dlc/10dlc-rate-limits) for campaign-specific limits
- **Voice API**: Standard API rate limits apply to call control endpoints
- **Cloud Storage**: Rate limits apply to S3-compatible operations
---
### API Reliability & Retries
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/reliability/command-retries.md
When building applications with Telnyx APIs, you may encounter various reliability challenges that require robust error handling and retry strategies. These patterns apply across all Telnyx services including Voice, Messaging, Cloud Storage, and more.
## Common Reliability Challenges
Applications may encounter the following situations across any Telnyx API:
- **5XX Errors**: Server errors (500, 501, 503, 504) that indicate temporary service issues
- **Network Timeouts**: Requests that don't complete within expected timeframes
- **Duplicate Responses**: Identical responses that may occasionally be delivered
## Best Practices for API Reliability
Telnyx carefully monitors all API platforms for 5XX errors, latency, and duplicate responses, and actively works to keep all of these to a minimum across all services.
For added reliability, there are several steps developers can take to handle errors, latency, and duplicate responses across any Telnyx API:
### **Retry Strategies**
- **Retry on 5XX Errors**: If your application receives a 500-level error, implement exponential backoff and retry
- **Timeout Handling**: If your application fails to receive an HTTP response within a reasonable timeframe (typically 500ms-5s depending on the operation), retry the request
- **Maximum Retry Attempts**: Implement a maximum retry limit (typically 3-5 attempts) to avoid infinite loops
### **Error Handling Patterns**
- **Exponential Backoff**: Increase wait time between retries (e.g., 1s, 2s, 4s, 8s)
- **Circuit Breaker**: Temporarily stop making requests if error rates exceed thresholds
- **Graceful Degradation**: Design your application to continue functioning even when some API calls fail
---
### Webhook Fundamentals
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/webhooks/receiving-webhooks.md
One application can provide another application with real-time updates via a webhook (also referred to as a web callback or HTTP push API). A webhook delivers data to other applications as it happens, meaning you get data immediately. In the past, APIs would typically need to poll for data very frequently to get it promptly. This makes webhooks much more efficient for both providers and consumers. The only drawback to webhooks is the difficulty of initially setting them up - [this](/docs/messaging/messages/send-receive-mms) tutorial walks through how to consume webhooks.
Webhooks are sometimes referred to as "Reverse APIs," as they give you what amounts to an API spec, and you must design an API for the webhook to use. The webhook will make an HTTP request to your app (typically a POST), and you will then be charged with interpreting it.
Telnyx can send webhook events that notify your application any time an event happens on your account. This is especially useful for events like receiving an SMS or MMS message and getting feedback on Voice API events. The [messaging webhooks](/docs/messaging/messages/receiving-webhooks) section goes into a bit more detail on how SMS and MMS webhooks work.
The [machine-readable webhook event catalog](https://developers.telnyx.com/data/webhook-events.json) contains the concrete request payload, media type, source specification, and publication selector for every canonical Telnyx webhook. Use the catalog when callback-page Markdown exports do not include the OpenAPI request example.
## Delivery contract
Apply the following handling sequence:
1. Preserve the raw request body and the `telnyx-timestamp` and `telnyx-signature-ed25519` headers.
2. Verify the signature before trusting or queuing the event.
3. Record the event identifier and the product-specific correlation identifiers.
4. Return a `2xx` response promptly. Perform network calls and other long-running work asynchronously.
5. Process the queued event idempotently. Treat the event identifier as the deduplication key where the product envelope supplies one.
Do not depend on delivery order or single delivery. Events can be concurrent, duplicated, delayed, or delivered out of order. Reconcile state using `occurred_at` and product resource identifiers where those fields exist; do not use arrival time as authoritative event order.
Primary URL, failover URL, timeout, and retry behavior are configured and documented by product. A failed primary delivery can be retried or sent to a configured failover URL. Do not assume one retry schedule applies to every Telnyx product.
## Webhook Setup Options
Choose one of the following options based on your development stage:
### Option A: Local Development with ngrok (Recommended for Testing)
1. Install ngrok following our [ngrok setup guide](/docs/development/development-tools/ngrok-setup).
2. Start your local webhook server (see example below).
3. Create a tunnel: `ngrok http 3000`.
4. Use the provided HTTPS URL (e.g., `https://abc123.ngrok.io/webhooks`).
### Option B: Quick Testing with webhook.site
1. Visit [webhook.site](https://webhook.site).
2. Copy your unique URL.
3. Use this for initial testing (note: this won't allow you to respond to webhooks).
### Option C: Production Deployment
Deploy your webhook handler to a cloud service like:
- AWS Lambda with API Gateway.
- Google Cloud Functions.
- Heroku.
- DigitalOcean App Platform.
## Webhook delivery characteristics
Webhook consumers must support these delivery characteristics:
- **Does not guarantee delivery order**: Webhooks may arrive out of sequence
- **Retries failed delivery**: Retry timing and failover behavior depend on the product configuration
- **Delivers concurrently**: Multiple webhooks may arrive simultaneously
As a result, your application should be prepared to handle:
- **Out-of-order webhooks**: Events may not arrive in chronological order
- **Simultaneous webhooks**: Multiple events may be delivered at the same time
- **Duplicate webhooks**: The same event may be delivered more than once
## Handling Duplicate Events
Duplicate webhooks can cause your application to process the same event multiple times. To prevent this:
- **Use idempotency keys**: Include unique identifiers in your API requests (such as `command_id`, `idempotency_key`, etc.)
- **Implement deduplication**: Track processed webhook IDs to avoid duplicate processing
- **Design idempotent operations**: Ensure that processing the same event multiple times has no adverse effects
## Webhook payload structure
JSON event envelopes commonly contain these identification fields. TeXML callbacks use `application/x-www-form-urlencoded` fields instead. Consult the [webhook event catalog](https://developers.telnyx.com/data/webhook-events.json) for the exact media type and payload for each callback.
- **Event ID**: Unique identifier for the webhook event
- **Timestamp**: When the event occurred
- **Resource IDs**: Identifiers that correlate the webhook with your resources (calls, messages, etc.)
- **Event Type**: Describes what action triggered the webhook
## Security & Protocols
### HTTP and HTTPS
- Unsecure (HTTP) URLs are allowed for webhooks.
- If HTTPS (TLS) is used, the certificate will be validated.
### Event type naming
Where possible, events map to the C(R)UD operations, but this is certainly not always be applicable.
- resource.created
- resource.updated
- resource.deleted
When the CRUD operations are not applicable, events will be named with past tense verbs.
- message.created
- message.deleted
- message.delivered
- message.received
- porting_sub_request.ported
- porting_sub_request.closed
## Webhook structure
The top-level structure varies by product and protocol. Voice API and Messaging use different JSON envelopes; TeXML uses form-encoded callbacks. Within a product family, `event_type` or an equivalent field determines the event-specific payload. Parse according to the documented media type and event schema rather than assuming a universal envelope.
### Voice API top-level structure
```json
{
"call_leg_id": "e97d8d4c-1a25-11cd-bc67-02620a0f6d42",
"call_session_id": "e97da4f0-1a25-11bd-909f-02620a0f6d642",
"event_timestamp": "2019-11-10T22:25:27.521992Z",
"metadata": {
"attempt": 1,
"delivered_to": "https://www.example.com/callback",
"event": {
"event_type": "call.initiated",
"id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
"occurred_at": "2019-11-10T22:25:27.521992Z",
"payload": {
...
},
"record_type": "event"
},
"status": "delivered"
},
"name": "call.initiated",
"organization_id": null,
"type": "webhook",
"user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}
```
| FIELD NAME | DESCRIPTION |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `call_leg_id` | ID that is unique to the call and can be used to correlate webhook events. |
| `call_session_id` | ID that is unique to the call session and can be used to correlate webhook events. |
| `event_timestamp` | [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) datetime of when the event occurred. |
| `attempt` | The number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx `HTTP 200 OK` on receipt of the webhook. |
| `delivered_to` | URL that the webhook was sent to. |
| `event_type` | The type of event being delivered which also determines the structure of the `payload`. |
| `id` | Unique ID of the event. |
| `occurred_at` | [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) datetime of when the event occurred. |
| `record_type` | Will always be `event`. |
| `status` | Status of the webhook for debugging purposes. |
| `name` | Event name. |
| `organization_id` | ID of the organization. |
### Messaging top-level structure
```json
{
"data": {
"event_type": "message.finalized",
"id": "4ef8c3a6-4195-4389-b3a6-38e3cb9eb4ae",
"occurred_at": "2019-11-10T22:30:14.148+00:00",
"payload": {
...
},
"record_type": "event"
},
"meta": {
"attempt": 1,
"delivered_to": "https://www.example.com/messaging"
}
}
```
| FIELD NAME | DESCRIPTION |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_type` | The type of event being delivered which also determines the structure of the `payload`. |
| `id` | Unique ID of the event. |
| `occurred_at` | [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) datetime of when the event occurred. |
| `payload` | The main data for the event. The structure is denoted by the `event_type`. |
| `record_type` | Will always be `event`. |
| `attempt` | The number of attempts made to deliver the webhook. Multiple attempts will occur if your application does not send Telnyx a `2xx` HTTP status code within 2s of receipt of the webhook. |
| `delivered_to` | URL that the webhook was sent to. |
## Example: Receiving a Webhook
When you place an incoming call to a number associated with your Voice API Application, you will receive a callback for the incoming call. It should look something like the JSON below:
```json
{
"data": {
"record_type": "event",
"event_type": "call.initiated",
"id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
"occurred_at": "2018-02-02T22:25:27.521992Z",
"payload": {
"call_control_id": "d14dbcee-880b-11eb-8204-02420a0f7568",
"connection_id": "7267xxxxxxxxxxxxxx",
"call_leg_id": "d14dbcee-880b-11eb-8204-02420a0f7568",
"call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
"client_state": "aGF2ZSBhIG5pY2UgZGF5ID1d",
"from": "+1-202-555-0133",
"to": "+12025550131",
"direction": "incoming",
"state": "parked"
}
},
"meta": {
"attempt": 1,
"delivered_to": "http://example.com/webhooks"
}
}
```
> **Note:** After pasting the above content, Kindly check and remove any new line added
Field
Value
record_type
Description of the record.
event_type
The type of event detected by the Telnyx system
id
unique id for the webhook
occurred_at
ISO-8601 datetime of when event occured
call_control_id
call id used to issue commands via Voice API
connection_id
Voice API App ID (formerly Telnyx connection ID) used in the call.
call_leg_id
ID that is unique to the call and can be used to correlate webhook events
call_session_id
ID that is unique to the call session and can be used to correlate webhook events. Call session is a group of related call legs that logically belong to the same phone call, e.g. an inbound and outbound leg of a transferred call.
client_state
State received from a command
from
Number or SIP URI placing the call
to
Destination number or SIP URI of the call
direction
Whether the call is 'incoming' or 'outgoing'
state
Whether the call is in 'bridging' or 'parked' state
### Full Voice API example
```json
{
"call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
"call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
"event_timestamp": "2019-11-10T22:26:27.521992Z",
"metadata": {
"attempt": 1,
"delivered_to": "https://www.example.com/callback",
"event": {
"event_type": "call.answered",
"id": "0ccc7b54-4df3-4bca-a65a-3da1ecc777f0",
"occurred_at": "2019-11-10T22:26:27.521992Z",
"payload": {
"call_control_id": "v2:F5_vIJVqrosogeY_2L_JhCEHd2Dh-x4xz7tROTbh34tg6Zsk4JJc-w",
"call_leg_id": "428c31b6-7af4-4bcb-b7f5-5013ef9657c1",
"call_session_id": "428c31b6-abf3-3bc1-b7f4-5013ef9657c1",
"client_state": null,
"connection_id": "7267xxxxxxxxxxxxxx",
"from": "+8005550199",
"start_time": "2019-11-10T22:26:26.521992Z",
"to": "+8005550100"
},
"record_type": "event"
},
"status": "delivered"
},
"name": "call.answered",
"organization_id": null,
"type": "webhook",
"user_id": "901dbc74-1597-4d15-aad2-xxxxxxxxxxxx"
}
```
## Responding to a webhook
To acknowledge receipt of a webhook, return a `2xx` HTTP status code. Response headers and bodies are not used to process the event. Responses outside the `2xx` range, including redirects, indicate failed delivery.
## Retries
Treat timeout, network, and non-`2xx` responses as possible retry conditions. Product-specific retry and failover policies determine the attempts and destinations. The endpoint must tolerate repeated delivery even after an earlier attempt completed processing but its acknowledgment was not observed.
## Best practices
Return the acknowledgment before performing complex logic or network calls. Queue the verified event, return `2xx`, and process it asynchronously.
Make event processing idempotent. Store processed event identifiers with a retention period appropriate to the product, and make resource updates conditional so replaying an event has no additional effect. Verify webhook signatures before recording an event as accepted. Log the event identifier, event type, delivery attempt when present, and product resource identifiers for correlation and failure analysis.
## Webhook signing
Telnyx signs the webhook events it sends to clients so that the authenticity of the request can be verified. Webhook signing in API V2 uses public key encryption. Telnyx stores a public-private key pair and uses the private key to sign the payload. The public key is available to you so that you can verify the request.
The public key can be viewed in the [Mission Control Portal](https://portal.telnyx.com/#/api-keys/public-key).
The signature for the payload is calculated by building a string that is the combination of the timestamp of when the request was initiated, the pipe `|` character and the JSON payload. The signature is then `Base64` encoded.
```ruby
Base64.encode64("#{timestamp}|#{payload}")
```
The signature (`Base64` encoded) and the timestamp (in Unix format) are assigned to the request headers `telnyx-signature-ed25519` and `telnyx-timestamp` respectively.
You can then use cryptographic libraries in your language of choice to verify the signature using the public key. Refer to the [Telnyx SDKs](/docs/development/sdk) for implementation examples in your preferred language.
---
### Parameters & Field Names
> Source: https://developers.telnyx.com/docs/development/api-fundamentals/data-standards/parameters-fields.md
The Parameter & Field names section provides an overview of patterns for API request and response parameters and field names.
## Data Types
### Booleans
Boolean values are presented as `true` and `false` values. They will not be `1` or `0` nor will they be strings such as "true" and "false".
### Date-times
All date-times are represented in UTC with precisely the following format: `YYYY-MM-DDThh:mm:ss.fffZ` where `fff` is the first three decimals of the fractional seconds (i.e., millisecond precision).
API V2 accepts date-times in _at least_ the following 12 formats:
- `YYYY-MM-DDThh:mm:ss.fffZ`
- `YYYY-MM-DDThh:mm:ssZ`
- `YYYY-MM-DDThh:mmZ`
- The above with `-00`, `-0000`, or `-00:00` instead of the `Z` timezone identifier.
### Times (no date portion)
All times are represented in UTC with precisely the following format: `hh:mm:ss.fffZ` where `fff` is the first three decimals of the fractional seconds (i.e., millisecond precision).
### Durations
If a parameter represents a unit of time, then the unit name should be part of the field name so that the consumer knows what the value represents. For example, a retry timeout value would be named `retry_timeout_secs` or `retry_timeout_millis`.
Valid field suffixes are:
- millis
- secs
- hours
- days
- weeks
- months
- years
API V2 does not use ISO8601 time durations (e.g. `P4Y`, `PT0,42M` or `P3Y6M4DT12H30M5.423S`).
### Time zones
Time zone field names are always spelled as `timezone` and the value is always the Time Zone Database area name spelled out as `Europe/Berlin`, `America/Chicago` for example.
## Date Literals
User-friendly date ranges use this naming convention.
| Date Literal | Range |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| yesterday | Starts 00:00:00 the day before and continues for 24 hours. |
| today | Starts 00:00:00 of the current day and continues for 24 hours. |
| tomorrow | Starts 00:00:00 after the current day and continues for 24 hours. |
| last_week | Starts 00:00:00 on the first day of the week before the most recent first day of the week and continues for seven full days. |
| this_week | Starts 00:00:00 on the most recent first day of the week before the current day and continues for seven full days. |
| next_week | Starts 00:00:00 on the most recent first day of the week after the current day and continues for seven full days. |
| last_month | Starts 00:00:00 on the first day of the month before the current day and continues for all the days of that month. |
| this_month | Starts 00:00:00 on the first day of the month that the current day is in and continues for all the days of that month. |
| next_month | Starts 00:00:00 on the first day of the month after the month that the current day is in and continues for all the days of that month. |
| last_N_hours | For the number n provided, starts at 00 of the last hour and continues for the past n hours. |
| next_N_hours | For the number n provided, starts at 00 of the next hour and continues for the next n hours. |
| last_N_days | For the number n provided, starts 00:00:00 of the current day and continues for the past n days. |
| next_N_days | For the number n provided, starts 00:00:00 of the current day and continues for the next n days. |
| last_N_weeks | For the number n provided, starts 00:00:00 of the last day of the previous week and continues for the past n weeks. |
| next_N_weeks | For the number n provided, starts 00:00:00 of the first day of the next week and continues for the next n weeks. |
## HTTP Headers
Date-times in HTTP headers follow [RFC-7231 §7.1.1.1](https://www.rfc-editor.org/rfc/rfc7231)'s recommended "IMF-fixdate" format.
An example of the preferred format is
Sun, 06 Nov 1994 08:49:37 GMT ; IMF-fixdate
## Naming Conventions
### Enums and string literals
Enum and string literal parameters use snake case. If there is an acronym involved, there will not be an underscore between every letter.
For example, `by_ani` instead of`ByANI`, `byAni`, or `by_a_n_i`.
### Country codes
The field name `country_code` is always used to represent a country. It will be in [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) format in capital letters to represent the country. For example `DE` for Germany.
### Phone numbers
Phone numbers are always specified in [e164](https://en.wikipedia.org/wiki/E.164) format. For example, `+18005550199`.
If the country calling code needs to be represented in the API, the field name will always be `country_calling_code`. If representing the actual country via its alpha 2 representation, `country_code` will be used.
Ex: `{"country_calling_code": "1", "country_code": "US"}`
### City names
City names are always called `locality` and represented in title case. For example, `New York City` instead of `NEW YORK CITY`.
## Address Format
Addresses are represented like this:
```json
{
"street_address": "311 W Superior St",
"extended_address": "Suite 504",
"locality": "Chicago",
"administrative_area": "IL"
"country_code": "US",
"postal_code": "60654"
}
```
### U.S. addresses
US states are always represented in their two-digit form in capital letters. For example, `NY` for New York.
## Pagination
The parameter which contains pagination is `page`. This parameter is a map of pagination attributes.
### Example
`GET /phone_numbers?page[number]=3&page[size]=1 HTTP/1.1`
The default number of items per page is 20; however, sometimes, this may not be appropriate.
Page numbering is 1-based and omitting the `page`, or the `page[number]` parameter will return the first page.
Generally speaking, the maximum allowable results will not be more than 250, although there may be some exceptions to this rule.
The total number of results is provided in the `total_pages` field so that clients will know how many page options to display.
### Example Response
```bash
HEADERS
Total-Pages:13
```
Response:
```json
{
"meta": {
"total_pages": 13,
"total_results": 26,
"page_number": 3,
"page_size": 2
},
"data": [
{
"record_type": "phone_number",
"id": "4567890987",
"phone_number": "+18005550100",
"purchased_at": "2015-05-22T14:56:29.000Z",
...
},
{
"record_type": "phone_number",
"id": "44568890987",
"phone_number": "+18005550199",
"purchased_at": "2015-05-22T14:56:29.000Z",
...
}
]
}
```
## Sorting
An endpoint may support requests to sort the primary data with a `sort` query parameter.
### Example
```bash
GET /connections?sort=name HTTP/1.1
```
Unless not appropriate, the default sort will be `created_at DESC`
An endpoint may also support multiple sort fields using the array syntax. Sort fields will be applied in the order specified.
### Multiple Sort Fields
```bash
GET /connections?sort[]=name&sort[]=created_at HTTP/1.1
```
The sort order for each sort field will be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, "-"), in which case it will be descending.
```bash
GET /connections?sort[]=-created_at&sort[]=name HTTP/1.1
```
The above example should return the newest connections first. Any connections created on the same date will then be sorted by their name in ascending alphabetical order.
## Filtering
Filtering of a resource collection based upon associations do so by allowing query parameters that combine the filter with the association name.
For example, the following is a request for all phone_numbers associated with a particular tag:
```bash
GET /phone_numbers?filter[tag]=tag_one HTTP/1.1
```
Filtering to values within an array can be achieved using query parameter array syntax:
```bash
GET /phone_numbers?filter[tag][]=tag_one&filter[tag][]=tag_two HTTP/1.1
```
Or an example using comments:
```bash
GET /comments?filter[tag]=tag_one,tag_two HTTP/1.1
```
Use the string `null` to filter on resources that don't have a particular value set:
```bash
GET /comments?filter[author]=null HTTP/1.1
```
### Filtering on values of nested or related objects
To denote that a filter applies to an attribute of a nested object, use the dot notation.
For example, the phone numbers endpoint returns data in this format:
```json
{
"id": "d460a653-8ee6-4061-ae9a-5b8a52539fb4",
"phone_number": "18005550199",
"record_type": "phone_number",
...
"voice": {
"e911_address_id" : "",
"connection_name" : false,
"inbound_call_recording_channels" : "single",
...
}
}
```
To filter by the connection name the path and request would look like:
```bash
GET /phone_numbers?filter[voice.connection_name]=conn_one HTTP/1.1
```
Similarly by connection ID:
```bash
GET /regions?filter[voice.connection_id]=d460a653-8pp6-4061-ae9a-5b8a57339fb4 HTTP/1.1
```
However, if `name` was a top-level key as in the below example:
```json
{
"id": "d460a653-8pp6-4061-ae9a-5b8a57339fb4",
"name": "conn_one",
"record_type": "connection",
...
}
```
then the query would be:
```bash
GET /connections?filter[name]=conn_one HTTP/1.1
```
### Complex filters
When filtering, you may need to specify more complex filters than `equal to`.
Options are:
- `eq`
- `ne`
- `gt`
- `gte`
- `lt`
- `lte`
- `starts_with`
- `ends_with`
- `contains`
Return phone numbers purchased before 2018-02-21:
```bash
GET /phone_numbers?filter[purchased_at][lt]=2018-02-21 HTTP/1.1
```
If using `eq` then:
```bash
GET /phone_numbers?filter[purchased_at][eq]=2018-02-21 HTTP/1.1
```
and:
```bash
GET /phone_numbers?filter[purchased_at]=2018-02-21 HTTP/1.1
```
are equivalent.
To filter using string data use `starts_with`, `ends_with` or `contains`:
```bash
GET /phone_numbers?filter[voice.connection_name][contains]=conn HTTP/1.1
```
---
## Server-side SDKs
### Node.js
> Source: https://developers.telnyx.com/docs/development/sdk/node.md
---
### Python
> Source: https://developers.telnyx.com/docs/development/sdk/python.md
---
### PHP
> Source: https://developers.telnyx.com/docs/development/sdk/php.md
```php
$region,
'version' => 'latest',
'endpoint' => $endpoint,
'credentials' => [
'key' => $telnyxAPIKey,
'secret' => $telnyxAPIKey,
],
'use_path_style_endpoint' => true
]);
$bucketName = "test-bucket-" . $region . '-' . date('H-i') . '-' . rand(0, 1000000);
echo "Generated bucket name: " . $bucketName . PHP_EOL;
// 2. Create a bucket
try {
$s3Client->createBucket([
'Bucket' => $bucketName
]);
echo "Created bucket: {$bucketName}" . PHP_EOL;
} catch (AwsException $e) {
die("Unable to create bucket: " . $e->getMessage());
}
// 3. Upload two objects with random data
for ($i = 0; $i < 2; $i++) {
$content = random_bytes(1024 * 32); // 32KB of random data
$objName = "{$i}.txt";
try {
$s3Client->putObject([
'Bucket' => $bucketName,
'Key' => $objName,
'Body' => $content
]);
echo "Uploaded file ({$objName}) to bucket: {$bucketName}" . PHP_EOL;
} catch (AwsException $e) {
die("Unable to upload file ({$objName}): " . $e->getMessage());
}
}
// 4. List objects in the bucket
try {
$result = $s3Client->listObjects([
'Bucket' => $bucketName
]);
foreach ($result['Contents'] as $item) {
echo "Listed object: " . $item['Key'] . PHP_EOL;
}
} catch (AwsException $e) {
die("Unable to list objects: " . $e->getMessage());
}
// 5. Download the first object
try {
$result = $s3Client->getObject([
'Bucket' => $bucketName,
'Key' => '1.txt'
]);
$data = $result['Body']->getContents();
echo "Downloaded file size: " . strlen($data) . PHP_EOL;
} catch (AwsException $e) {
die("Unable to download object: " . $e->getMessage());
}
// 6. Create a presigned URL for the first file
$url = "https://api.telnyx.com/v2/storage/buckets/{$bucketName}/1.txt/presigned_url";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['TTL' => 30]));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer ' . $telnyxAPIKey,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpcode != 200) {
die("Unexpected status code: {$httpcode} | response: {$response}");
}
$presignedData = json_decode($response, true);
$presignedURL = $presignedData['data']['presigned_url'];
echo "Generated presigned URL: {$presignedURL}" . PHP_EOL;
// 7. Download the file using the presigned URL
$ch = curl_init($presignedURL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
echo "Downloaded presigned URL data size: " . strlen($result) . PHP_EOL;
?>
```
---
### Java
> Source: https://developers.telnyx.com/docs/development/sdk/java.md
## Add Dependency
```
software.amazon.awssdk
s3
2.20.0
```
## Create S3 Bucket
```
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
public class CreateBucket {
public static void main(String[] args) {
String bucketName = "--your-bucket-name--";
Region region = Region.US_EAST_1;
String telnyxUrl = "https://us-central-1.telnyxcloudstorage.com";
String telnyxApiKey = "-- api key --";
// Create an S3 client
S3Client s3 = S3Client.builder()
.region(region)
.endpointOverride(URI.create(telnyxUrl))
// Only perform CRC checks `when_required`
.requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
.responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
.credentialsProvider(
StaticCredentialsProvider.create(AwsBasicCredentials.create(telnyxApiKey, "does not matter")))
.build();
// create bucket
CreateBucketRequest createBucketRequest = CreateBucketRequest.builder()
.bucket(bucketName)
.build();
s3.createBucket(createBucketRequest);
System.out.println("Bucket created successfully: " + bucketName);
// Close the S3 client
s3.close();
}
}
```
## Upload an Object
```
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import java.net.URI;
import java.nio.file.Paths;
public class UploadObjectToS3 {
public static void main(String[] args) {
String bucketName = "--your-bucket-name--";
String keyName = "your-object-key";
String filePath = "--path to file for upload--";
Region region = Region.US_EAST_1;
String telnyxUrl = "https://us-central-1.telnyxcloudstorage.com";
String telnyxApiKey = "--your api key --";
// Create an S3 client
S3Client s3 = S3Client.builder()
.region(region)
.endpointOverride(URI.create(telnyxUrl))
.credentialsProvider(
StaticCredentialsProvider.create(AwsBasicCredentials.create(telnyxApiKey, "does not matter")))
.build();
// upload object
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
.bucket(bucketName)
.key(keyName)
.build();
// Upload the file to S3
s3.putObject(putObjectRequest, RequestBody.fromFile(Paths.get(filePath)));
// Close the S3 client
s3.close();
}
}
```
## List Objects
```
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Object;
import java.net.URI;
public class ListObjects {
public static void main(String[] args) {
String bucketName = "--your-bucket-name--";
Region region = Region.US_EAST_1;
String telnyxUrl = "https://us-central-1.telnyxcloudstorage.com";
String telnyxApiKey = "--your api key --";
// Create an S3 client
S3Client s3 = S3Client.builder()
.region(region)
.endpointOverride(URI.create(telnyxUrl))
.credentialsProvider(
StaticCredentialsProvider.create(AwsBasicCredentials.create(telnyxApiKey, "does not matter")))
.build();
// Create a ListObjectsV2Request
ListObjectsV2Request listObjectsRequest = ListObjectsV2Request.builder()
.bucket(bucketName)
.build();
// Get the list of objects in the bucket
ListObjectsV2Response listObjectsResponse = s3.listObjectsV2(listObjectsRequest);
for (S3Object s3Object : listObjectsResponse.contents()) {
System.out.println( s3Object.key());
}
// Close the S3 client
s3.close();
}
}
```
## Download Object
```
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
public class DownloadObject {
public static void main(String[] args) throws IOException {
String bucketName = "--your-bucket-name--";
Region region = Region.US_EAST_1;
String telnyxUrl = "https://us-central-1.telnyxcloudstorage.com";
String telnyxApiKey = "--your api key --";
String keyName = "your-object-key";
S3Client s3 = S3Client.builder()
.region(region)
.endpointOverride(URI.create(telnyxUrl))
.credentialsProvider(
StaticCredentialsProvider.create(AwsBasicCredentials.create(telnyxApiKey, "does not matter")))
.build();
// Create a GetObjectRequest
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucketName)
.key(keyName)
.build();
// Download the object and transform the response to a byte array
ResponseBytes objectBytes = s3.getObject(getObjectRequest, ResponseTransformer.toBytes());
// Write the file to the specified path
File downloadedFile = new File("-- path to where to save the file --");
try (FileOutputStream fos = new FileOutputStream(downloadedFile)) {
fos.write(objectBytes.asByteArray());
System.out.println("File downloaded successfully to -- path to where to save the file --");
}
// Close the S3 client
s3.close();
}
}
```
## Generate Presigned URLs for Upload and Download
In order for this part to work, we will need to add json decoding library and http client. Any libraries will do, but for this example we picked: gson and okhttp3.
```
com.squareup.okhttp3
okhttp
4.9.2
com.google.code.gson
gson
2.8.7
```
```
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import okhttp3.*;
import java.io.IOException;
import java.util.Map;
public class GeneratePresignedURLAndDownloadObject {
public static void main(String[] args) throws IOException {
OkHttpClient httpClient = new OkHttpClient();
Gson gson = new Gson();
String presignedUrlRequestJson = gson.toJson(Map.of("TTL", 30));
RequestBody presignedUrlRequestBody = RequestBody.create(MediaType.parse("application/json"), presignedUrlRequestJson);
Request presignedUrlRequest = new Request.Builder()
.url("https://api.telnyx.com/v2/storage/buckets/-- name of the bucket --/--name of the object--/presigned_url")
.header("Authorization", "Bearer --your api key---")
.post(presignedUrlRequestBody)
.build();
try (Response response = httpClient.newCall(presignedUrlRequest).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to create presigned URL: " + response);
}
String responseBody = response.body().string();
Map responseBodyMap = gson.fromJson(responseBody, new TypeToken