Skip to content

Code Examples

Complete code examples for integrating TextFlow API into your applications.

Before running these examples:

  1. Get your API key from Settings → API Keys
  2. Replace sk_live_your_api_key_here with your actual API key
  3. Use a test key (sk_test_*) for development
Terminal window
# Send a basic SMS
curl -X POST https://textflow.telair.net/api/v1/messages/send \
-H "X-API-Key: sk_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"to": "+15551234567",
"message": "Hello from TextFlow!"
}'
import requests
def send_sms(to, message):
"""Send an SMS message using TextFlow API"""
url = "https://textflow.telair.net/api/v1/messages/send"
headers = {
"X-API-Key": "sk_live_your_api_key_here",
"Content-Type": "application/json"
}
payload = {
"to": to,
"message": message
}
response = requests.post(url, json=payload, headers=headers)
return response.json()
# Usage
result = send_sms("+15551234567", "Hello from Python!")
print(result)
const axios = require('axios');
async function sendSMS(to, message) {
try {
const response = await axios.post(
'https://textflow.telair.net/api/v1/messages/send',
{
to: to,
message: message
},
{
headers: {
'X-API-Key': 'sk_live_your_api_key_here',
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
console.error('Error sending SMS:', error.response.data);
throw error;
}
}
// Usage
sendSMS('+15551234567', 'Hello from Node.js!')
.then(result => console.log('Success:', result))
.catch(err => console.error('Failed:', err));
<?php
function sendSMS($to, $message) {
$url = 'https://textflow.telair.net/api/v1/messages/send';
$data = [
'to' => $to,
'message' => $message
];
$options = [
'http' => [
'header' => [
'X-API-Key: sk_live_your_api_key_here',
'Content-Type: application/json'
],
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return json_decode($result);
}
// Usage
$response = sendSMS('+15551234567', 'Hello from PHP!');
print_r($response);
?>
require 'net/http'
require 'json'
require 'uri'
def send_sms(to, message)
uri = URI('https://textflow.telair.net/api/v1/messages/send')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.path)
request['X-API-Key'] = 'sk_live_your_api_key_here'
request['Content-Type'] = 'application/json'
request.body = {
to: to,
message: message
}.to_json
response = http.request(request)
JSON.parse(response.body)
end
# Usage
result = send_sms('+15551234567', 'Hello from Ruby!')
puts result
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type SMSRequest struct {
To string `json:"to"`
Message string `json:"message"`
}
type SMSResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data struct {
MessageID string `json:"messageId"`
To string `json:"to"`
From string `json:"from"`
Status string `json:"status"`
} `json:"data"`
}
func sendSMS(to, message string) (*SMSResponse, error) {
url := "https://textflow.telair.net/api/v1/messages/send"
payload := SMSRequest{
To: to,
Message: message,
}
jsonData, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("X-API-Key", "sk_live_your_api_key_here")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result SMSResponse
json.Unmarshal(body, &result)
return &result, nil
}
func main() {
result, err := sendSMS("+15551234567", "Hello from Go!")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Response: %+v\n", result)
}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class TextFlowClient
{
private readonly HttpClient _httpClient;
private const string ApiKey = "sk_live_your_api_key_here";
private const string BaseUrl = "https://textflow.telair.net/api";
public TextFlowClient()
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("X-API-Key", ApiKey);
}
public async Task<SMSResponse> SendSMSAsync(string to, string message)
{
var payload = new
{
to = to,
message = message
};
var content = new StringContent(
JsonSerializer.Serialize(payload),
Encoding.UTF8,
"application/json"
);
var response = await _httpClient.PostAsync(
$"{BaseUrl}/v1/messages/send",
content
);
var responseBody = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<SMSResponse>(responseBody);
}
}
public class SMSResponse
{
public bool Success { get; set; }
public string Message { get; set; }
public SMSData Data { get; set; }
}
public class SMSData
{
public string MessageId { get; set; }
public string To { get; set; }
public string From { get; set; }
public string Status { get; set; }
}
// Usage
var client = new TextFlowClient();
var result = await client.SendSMSAsync("+15551234567", "Hello from C#!");
Console.WriteLine($"Message ID: {result.Data.MessageId}");
import requests
import time
def send_sms_with_retry(to, message, max_retries=3):
"""Send SMS with automatic retry on rate limit"""
url = "https://textflow.telair.net/api/v1/messages/send"
headers = {
"X-API-Key": "sk_live_your_api_key_here",
"Content-Type": "application/json"
}
payload = {"to": to, "message": message}
for attempt in range(max_retries):
try:
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
result = response.json()
if result.get('success'):
print(f"✓ Message sent: {result['data']['messageId']}")
return result
else:
print(f"✗ Failed: {result.get('error')}")
return None
elif response.status_code == 429:
# Rate limited - wait and retry
print(f"Rate limited, retrying in 60 seconds... (attempt {attempt + 1}/{max_retries})")
time.sleep(60)
continue
elif response.status_code == 400:
# Bad request - don't retry
error = response.json().get('error', 'Unknown error')
print(f"✗ Bad request: {error}")
return None
elif response.status_code == 401:
# Authentication error - don't retry
print(f"✗ Authentication failed - check your API key")
return None
else:
print(f"✗ Unexpected error: {response.status_code}")
return None
except requests.exceptions.RequestException as e:
print(f"✗ Network error: {e}")
if attempt < max_retries - 1:
time.sleep(5)
continue
return None
print(f"✗ Failed after {max_retries} attempts")
return None
# Usage
send_sms_with_retry("+15551234567", "Hello with retry logic!")
const axios = require('axios');
class TextFlowClient {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://textflow.telair.net/api';
}
async sendSMS(to, message, from = null) {
try {
const response = await axios.post(
`${this.baseUrl}/v1/messages/send`,
{
to: to,
message: message,
...(from && { from: from })
},
{
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
}
}
);
return { success: true, data: response.data };
} catch (error) {
return {
success: false,
error: error.response?.data?.error || error.message
};
}
}
async sendBulk(recipients, message, delayMs = 100) {
const results = [];
for (const recipient of recipients) {
const result = await this.sendSMS(recipient, message);
results.push({
to: recipient,
...result
});
// Add delay between sends to avoid rate limiting
if (delayMs > 0) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
return results;
}
}
// Usage
const client = new TextFlowClient('sk_live_your_api_key_here');
const recipients = [
'+15551234567',
'+15559876543',
'+15555555555'
];
const message = 'Important update: Our store will be closed tomorrow.';
client.sendBulk(recipients, message, 100)
.then(results => {
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log(`Sent: ${successful} successful, ${failed} failed`);
// Show failed recipients
results.filter(r => !r.success).forEach(r => {
console.log(`Failed to send to ${r.to}: ${r.error}`);
});
});
import requests
import csv
class TextFlowClient:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = "https://textflow.telair.net/api"
def send_sms(self, to, message):
"""Send a single SMS"""
url = f"{self.base_url}/v1/messages/send"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
payload = {"to": to, "message": message}
try:
response = requests.post(url, json=payload, headers=headers)
return response.json()
except Exception as e:
return {"success": False, "error": str(e)}
def send_personalized_bulk(self, csv_file):
"""Send personalized messages from CSV file
CSV format:
phone,first_name,appointment_date
+15551234567,John,2024-12-15
+15559876543,Jane,2024-12-16
"""
results = {"sent": 0, "failed": 0, "errors": []}
with open(csv_file, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
# Personalize message with CSV data
message = f"Hi {row['first_name']}! Your appointment is confirmed for {row['appointment_date']}. Reply CONFIRM or call (555) 123-4567."
result = self.send_sms(row['phone'], message)
if result.get('success'):
results['sent'] += 1
print(f"✓ Sent to {row['first_name']} ({row['phone']})")
else:
results['failed'] += 1
results['errors'].append({
'phone': row['phone'],
'error': result.get('error')
})
print(f"✗ Failed: {row['phone']} - {result.get('error')}")
return results
# Usage
client = TextFlowClient('sk_live_your_api_key_here')
results = client.send_personalized_bulk('appointments.csv')
print(f"\nResults: {results['sent']} sent, {results['failed']} failed")
config.js
require('dotenv').config();
const config = {
apiKey: process.env.TEXTFLOW_API_KEY,
baseUrl: process.env.TEXTFLOW_BASE_URL || 'https://textflow.telair.net/api',
environment: process.env.NODE_ENV || 'development'
};
module.exports = config;
// textflow.js
const axios = require('axios');
const config = require('./config');
class TextFlowClient {
constructor() {
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl;
if (!this.apiKey) {
throw new Error('TEXTFLOW_API_KEY environment variable is required');
}
// Warn if using production key in development
if (config.environment === 'development' && this.apiKey.startsWith('sk_live_')) {
console.warn('⚠️ WARNING: Using production API key in development mode');
}
}
async sendSMS(to, message) {
try {
const response = await axios.post(
`${this.baseUrl}/v1/messages/send`,
{ to, message },
{
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json'
}
}
);
return response.data;
} catch (error) {
throw new Error(error.response?.data?.error || error.message);
}
}
}
module.exports = TextFlowClient;
// .env file
// TEXTFLOW_API_KEY=sk_test_your_test_key_here
// TEXTFLOW_BASE_URL=https://textflow.telair.net/api
// NODE_ENV=development
// Usage
const TextFlowClient = require('./textflow');
const client = new TextFlowClient();
client.sendSMS('+15551234567', 'Hello!')
.then(result => console.log('Sent:', result))
.catch(error => console.error('Error:', error.message));
TextFlowClient.php
<?php
class TextFlowClient {
private $apiKey;
private $baseUrl = 'https://textflow.telair.net/api';
public function __construct($apiKey) {
$this->apiKey = $apiKey;
}
public function sendSMS($to, $message, $from = null) {
$url = $this->baseUrl . '/v1/messages/send';
$data = [
'to' => $to,
'message' => $message
];
if ($from) {
$data['from'] = $from;
}
$options = [
'http' => [
'header' => [
'X-API-Key: ' . $this->apiKey,
'Content-Type: application/json'
],
'method' => 'POST',
'content' => json_encode($data)
]
];
$context = stream_context_create($options);
$result = @file_get_contents($url, false, $context);
if ($result === false) {
return ['success' => false, 'error' => 'Failed to connect'];
}
return json_decode($result, true);
}
}
// order_confirmation.php
require_once 'TextFlowClient.php';
function sendOrderConfirmation($orderId, $customerPhone, $customerName, $total, $estimatedDelivery) {
$client = new TextFlowClient(getenv('TEXTFLOW_API_KEY'));
$message = "Hi {$customerName}! Your order #{$orderId} for \${$total} is confirmed. "
. "Estimated delivery: {$estimatedDelivery}. "
. "Track your order at: https://yourstore.com/orders/{$orderId}";
$result = $client->sendSMS($customerPhone, $message);
if ($result['success']) {
// Log success in database
logNotification($orderId, 'sms', 'sent', $result['data']['messageId']);
return true;
} else {
// Log error
logNotification($orderId, 'sms', 'failed', $result['error']);
return false;
}
}
// Usage in checkout process
$orderComplete = processOrder($cartItems, $paymentInfo);
if ($orderComplete) {
sendOrderConfirmation(
$orderComplete['id'],
$customer['phone'],
$customer['name'],
$orderComplete['total'],
$orderComplete['estimated_delivery']
);
}
?>
textflow/client.py
import requests
from django.conf import settings
class TextFlowClient:
def __init__(self):
self.api_key = settings.TEXTFLOW_API_KEY
self.base_url = 'https://textflow.telair.net/api'
def send_sms(self, to, message):
url = f"{self.base_url}/v1/messages/send"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
payload = {"to": to, "message": message}
response = requests.post(url, json=payload, headers=headers)
return response.json()
# views.py
from django.http import JsonResponse
from .client import TextFlowClient
def send_verification_code(request):
phone = request.POST.get('phone')
code = generate_verification_code()
client = TextFlowClient()
result = client.send_sms(
phone,
f"Your verification code is: {code}. This code expires in 10 minutes."
)
if result.get('success'):
# Store code in session or database
request.session['verification_code'] = code
return JsonResponse({'success': True})
else:
return JsonResponse({
'success': False,
'error': result.get('error')
}, status=400)
# settings.py
TEXTFLOW_API_KEY = os.environ.get('TEXTFLOW_API_KEY')
app/Services/TextFlowService.php
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class TextFlowService
{
protected $apiKey;
protected $baseUrl = 'https://textflow.telair.net/api';
public function __construct()
{
$this->apiKey = config('services.textflow.key');
}
public function sendSMS($to, $message)
{
$response = Http::withHeaders([
'X-API-Key' => $this->apiKey,
'Content-Type' => 'application/json'
])->post("{$this->baseUrl}/v1/messages/send", [
'to' => $to,
'message' => $message
]);
return $response->json();
}
}
// config/services.php
return [
'textflow' => [
'key' => env('TEXTFLOW_API_KEY'),
],
];
// app/Http/Controllers/NotificationController.php
<?php
namespace App\Http\Controllers;
use App\Services\TextFlowService;
class NotificationController extends Controller
{
protected $textflow;
public function __construct(TextFlowService $textflow)
{
$this->textflow = $textflow;
}
public function sendOrderUpdate($orderId)
{
$order = Order::findOrFail($orderId);
$message = "Order #{$order->id} has been shipped! "
. "Track at: https://yourstore.com/track/{$order->tracking_number}";
$result = $this->textflow->sendSMS($order->customer_phone, $message);
if ($result['success']) {
$order->sms_sent_at = now();
$order->save();
}
return response()->json($result);
}
}
import unittest
from unittest.mock import patch, Mock
from textflow_client import TextFlowClient
class TestTextFlowClient(unittest.TestCase):
@patch('requests.post')
def test_send_sms_success(self, mock_post):
# Mock successful response
mock_response = Mock()
mock_response.json.return_value = {
'success': True,
'data': {
'messageId': 'msg_123',
'status': 'sent'
}
}
mock_post.return_value = mock_response
# Test
client = TextFlowClient('sk_test_123')
result = client.send_sms('+15551234567', 'Test message')
# Assertions
self.assertTrue(result['success'])
self.assertEqual(result['data']['messageId'], 'msg_123')
@patch('requests.post')
def test_send_sms_rate_limit(self, mock_post):
# Mock rate limit response
mock_response = Mock()
mock_response.status_code = 429
mock_response.json.return_value = {
'success': False,
'error': 'Daily message limit reached'
}
mock_post.return_value = mock_response
# Test
client = TextFlowClient('sk_test_123')
result = client.send_sms('+15551234567', 'Test message')
# Assertions
self.assertFalse(result['success'])
self.assertIn('limit', result['error'].lower())
if __name__ == '__main__':
unittest.main()