Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt

Use this file to discover all available pages before exploring further.

Bindings allow your edge functions to interact with Telnyx platform services. They provide secure, auto-authenticated access without managing API keys in your code.

Available Bindings

BindingDescriptionStatus
VoiceMake and receive calls✅ Available
MessagingSend SMS/MMS✅ Available
Phone NumbersManage numbers✅ Available
FaxSend faxes✅ Available
Verify2FA/verification✅ Available
Cloud StorageS3-compatible storage✅ Available
KVKey-value store🔜 Coming soon
SQL DBServerless database🔜 Coming soon

What is a Binding?

When you configure a binding for your function, you grant it the capability to access Telnyx services. The binding handles authentication automatically — your API key is never exposed in your code or logs.
Your Function → Binding Proxy → Telnyx API
      ↓              ↓              ↓
  Placeholder    Resolves      Actual API
  API Key        Credentials   Call Made
When you deploy a function with an active binding:
  1. Your function receives a JWT credential as the TELNYX_API_KEY environment variable
  2. Your function receives the binding proxy URL as TELNYX_BASE_URL
  3. API calls made to ${TELNYX_BASE_URL}/v2/<api-path> are routed through the binding proxy, which authenticates with your real API key
  4. The API call proceeds with proper authentication
Important: You must construct API URLs using TELNYX_BASE_URL — do not call https://api.telnyx.com directly. Direct calls will return 401 because the binding-injected JWT is not a standard Telnyx API key.
// ✅ Correct — use TELNYX_BASE_URL from binding
const baseUrl = process.env.TELNYX_BASE_URL;
const response = await fetch(`${baseUrl}/v2/messages`, {
    headers: { 'Authorization': `Bearer ${process.env.TELNYX_API_KEY}` }
});

// ❌ Wrong — direct calls to api.telnyx.com return 401 with binding JWT
const response = await fetch('https://api.telnyx.com/v2/messages', {
    headers: { 'Authorization': `Bearer ${process.env.TELNYX_API_KEY}` }
});
Notice the /v2/ in the URL path: ${TELNYX_BASE_URL}/v2/messages. Even though TELNYX_BASE_URL already contains a /v2/ segment in its path (e.g. .../v2/compute/internal/binding-proxy), you must still include /v2/ between the proxy URL and the API endpoint path.
Benefits:
  • API key never appears in function code
  • API key never appears in logs
  • Credentials can be rotated without code changes

Creating a Binding

One-time setup per organization:
# Create a binding for your organization
telnyx-edge bindings create

# Verify the binding works
telnyx-edge bindings validate

Managing Bindings

# View your current binding
telnyx-edge bindings get

# Validate the binding is working
telnyx-edge bindings validate

# Rotate binding credentials (recommended monthly)
telnyx-edge bindings update

# Remove the binding
telnyx-edge bindings delete

Using Bindings: Telnyx API

With a binding configured, use TELNYX_BASE_URL and TELNYX_API_KEY to make API calls through the binding proxy. The proxy handles authentication with your real API key.
const http = require('http');

const BASE_URL = process.env.TELNYX_BASE_URL;
const API_KEY = process.env.TELNYX_API_KEY;

http.createServer(async (req, res) => {
    if (req.url === '/health/liveness' || req.url === '/health/readiness') {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        return res.end('ok');
    }

    // Send a message via binding proxy
    const response = await fetch(`${BASE_URL}/v2/messages`, {
        method: 'POST',
        headers: {
            'Authorization': `Bearer ${API_KEY}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            from: '+12345678901',
            to: '+12345678902',
            text: 'Hello from Edge Compute!'
        })
    });

    const data = await response.json();
    res.writeHead(200, { 'Content-Type': 'application/json' });
    res.end(JSON.stringify(data));
}).listen(8080);

Using Bindings: Cloud Storage

The binding-injected TELNYX_API_KEY (a JWT) does not work for S3-compatible Cloud Storage operations. The Cloud Storage endpoint (*.telnyxcloudstorage.com) requires AWS SigV4 authentication with a valid AWS access key — the binding JWT is not a valid AWS credential and will be rejected.For Cloud Storage operations (ListObjectsV2, GetObject, PutObject, etc.), store a regular Telnyx API key as a secret and use it as the S3 access key:
telnyx-edge secrets add TELNYX_STORAGE_KEY YOUR_API_KEY
The binding proxy handles api.telnyx.com routes only. S3-compatible calls go directly to the storage endpoint.

Using Cloud Storage with a Secret

package main

import (
    "os"
    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/credentials"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3"
)

func getStorageClient() *s3.S3 {
    // Use a real API key stored as a secret, NOT the binding TELNYX_API_KEY
    apiKey := os.Getenv("TELNYX_STORAGE_KEY") // set via: telnyx-edge secrets add
    if apiKey == "" {
        apiKey = os.Getenv("TELNYX_API_KEY") // fallback: only works with real API key, not binding JWT
    }

    sess := session.Must(session.NewSession(&aws.Config{
        Endpoint:    aws.String("https://us-east-1.telnyxcloudstorage.com"),
        Region:      aws.String("us-east-1"),
        Credentials: credentials.NewStaticCredentials(
            apiKey,
            "", // Not required for Telnyx
            "",
        ),
    }))
    return s3.New(sess)
}

func listObjects(bucket string) ([]string, error) {
    client := getStorageClient()
    
    result, err := client.ListObjectsV2(&s3.ListObjectsV2Input{
        Bucket: aws.String(bucket),
    })
    if err != nil {
        return nil, err
    }
    
    var keys []string
    for _, obj := range result.Contents {
        keys = append(keys, *obj.Key)
    }
    return keys, nil
}
The binding proxy handles api.telnyx.com routes (Voice, Messaging, etc.) only. For S3-compatible operations against the Cloud Storage endpoint, use a regular Telnyx API key stored via telnyx-edge secrets add.

Using Bindings: KV

🔜 Coming soon — KV bindings will allow key-value storage directly from edge functions.

Using Bindings: SQL DB

🔜 Coming soon — SQL DB bindings will provide serverless database access from edge functions.

Bindings vs Secrets

FeatureBindingsSecrets
PurposeTelnyx service accessGeneral sensitive data
ScopeOne per organizationUnlimited per organization
CredentialsAuto-managed (JWT via proxy)User-provided
InjectionTELNYX_API_KEY (JWT), TELNYX_BASE_URL (proxy URL)Custom environment variables
Rotationbindings updateManual re-add
Use caseTelnyx SDK/API integrationDatabase passwords, external API keys
Use bindings for Telnyx service access — credentials are managed automatically. Use secrets for third-party services or when you need multiple different credentials.

Error Handling

import telnyx
from telnyx.error import TelnyxError, AuthenticationError, APIError

def safe_api_call():
    try:
        balance = telnyx.Balance.retrieve()
        return {"balance": balance.balance}

    except AuthenticationError as e:
        # Binding issue - credentials invalid or expired
        return {
            "error": "Authentication failed",
            "hint": "Try: telnyx-edge bindings update"
        }

    except APIError as e:
        # API-level error
        return {
            "error": f"API error: {e.message}",
            "code": e.code
        }

    except TelnyxError as e:
        # General Telnyx error
        return {"error": str(e)}

Troubleshooting

Binding not found

$ telnyx-edge bindings get
 No binding found

# Solution: Create a binding
$ telnyx-edge bindings create

Validation failed

$ telnyx-edge bindings validate
 Binding validation failed

# Solutions:
# 1. Update the binding
telnyx-edge bindings update

# 2. Check your Telnyx account status

# 3. Verify authentication
telnyx-edge auth status

Function can’t access Telnyx API

# Check binding exists
telnyx-edge bindings get

# Validate binding works
telnyx-edge bindings validate

# Redeploy function to get latest credentials
telnyx-edge ship