Skip to content

Messages API

The Messages API allows you to retrieve message history and check delivery status for SMS messages sent through your TextFlow account.

All message endpoints are available at:

https://textflow.telair.net/api/v1/messages

All requests require API key authentication via the X-API-Key header:

Terminal window
curl -H "X-API-Key: sk_live_your_api_key_here" \
https://textflow.telair.net/api/v1/messages

Retrieve a paginated list of messages.

GET /v1/messages
ParameterTypeDescription
pageintegerPage number (default: 1)
limitintegerResults per page, max 100 (default: 50)
directionstringFilter by "inbound" or "outbound"
statusstringFilter by status: "queued", "sent", "delivered", "failed"
tostringFilter by recipient phone number
fromstringFilter by sender phone number
Terminal window
curl -X GET "https://textflow.telair.net/api/v1/messages?page=1&limit=20&status=delivered" \
-H "X-API-Key: sk_live_your_api_key_here"
{
"success": true,
"data": [
{
"id": 12345,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"direction": "outbound",
"to": "+15551234567",
"from": "+15559876543",
"body": "Your order has shipped!",
"status": "delivered",
"errorMessage": null,
"segments": 1,
"sentAt": "2024-01-15T10:30:00Z",
"deliveredAt": "2024-01-15T10:30:05Z",
"createdAt": "2024-01-15T10:29:55Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 150,
"pages": 8
}
}

Retrieve a single message by ID or UUID to check its status.

GET /v1/messages/:id
ParameterTypeDescription
idstringMessage ID (numeric) or UUID
Terminal window
curl -X GET "https://textflow.telair.net/api/v1/messages/12345" \
-H "X-API-Key: sk_live_your_api_key_here"

Or using UUID:

Terminal window
curl -X GET "https://textflow.telair.net/api/v1/messages/550e8400-e29b-41d4-a716-446655440000" \
-H "X-API-Key: sk_live_your_api_key_here"
{
"success": true,
"data": {
"id": 12345,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"direction": "outbound",
"to": "+15551234567",
"from": "+15559876543",
"body": "Your order has shipped!",
"status": "delivered",
"errorMessage": null,
"segments": 1,
"sentAt": "2024-01-15T10:30:00Z",
"deliveredAt": "2024-01-15T10:30:05Z",
"createdAt": "2024-01-15T10:29:55Z",
"updatedAt": "2024-01-15T10:30:05Z"
}
}

Messages progress through the following statuses:

StatusDescription
queuedMessage is queued for sending
sentMessage has been sent to the carrier
deliveredMessage was delivered to the recipient
failedMessage failed to send or deliver

To check if a message was delivered, poll the message endpoint:

async function waitForDelivery(messageId, maxAttempts = 10) {
const API_KEY = 'sk_live_your_api_key_here';
for (let i = 0; i < maxAttempts; i++) {
const response = await fetch(
`https://textflow.telair.net/api/v1/messages/${messageId}`,
{ headers: { 'X-API-Key': API_KEY } }
);
const data = await response.json();
if (data.data.status === 'delivered') {
console.log('Message delivered!');
return data.data;
}
if (data.data.status === 'failed') {
console.error('Message failed:', data.data.errorMessage);
return data.data;
}
// Wait 2 seconds before next check
await new Promise(resolve => setTimeout(resolve, 2000));
}
console.log('Max attempts reached, message still pending');
return null;
}

StatusErrorDescription
401API key requiredMissing X-API-Key header
401Invalid or inactive API keyAPI key is invalid or revoked
403API access not enabledYour plan doesn’t include API access
404Message not foundMessage doesn’t exist or belongs to another organization
429Rate limit exceededToo many requests
{
"success": false,
"error": "Error message describing what went wrong"
}

import requests
import time
API_KEY = "sk_live_your_api_key_here"
BASE_URL = "https://textflow.telair.net/api"
def get_message(message_id):
"""Get a single message by ID"""
headers = {"X-API-Key": API_KEY}
response = requests.get(f"{BASE_URL}/v1/messages/{message_id}", headers=headers)
return response.json()
def list_messages(page=1, limit=50, status=None):
"""List messages with optional filters"""
headers = {"X-API-Key": API_KEY}
params = {"page": page, "limit": limit}
if status:
params["status"] = status
response = requests.get(f"{BASE_URL}/v1/messages", params=params, headers=headers)
return response.json()
def wait_for_delivery(message_id, max_attempts=10):
"""Poll for delivery status"""
for i in range(max_attempts):
result = get_message(message_id)
if result["success"]:
status = result["data"]["status"]
if status == "delivered":
return result["data"]
if status == "failed":
raise Exception(result["data"]["errorMessage"])
time.sleep(2 * (i + 1)) # Exponential backoff
return None
# Usage
messages = list_messages(status="delivered")
print(f"Found {messages['pagination']['total']} delivered messages")
message = get_message(12345)
print(f"Message status: {message['data']['status']}")
const axios = require('axios');
const API_KEY = 'sk_live_your_api_key_here';
const BASE_URL = 'https://textflow.telair.net/api';
async function getMessage(messageId) {
const response = await axios.get(`${BASE_URL}/v1/messages/${messageId}`, {
headers: { 'X-API-Key': API_KEY }
});
return response.data;
}
async function listMessages(params = {}) {
const response = await axios.get(`${BASE_URL}/v1/messages`, {
params,
headers: { 'X-API-Key': API_KEY }
});
return response.data;
}
async function waitForDelivery(messageId, maxAttempts = 10) {
for (let i = 0; i < maxAttempts; i++) {
const result = await getMessage(messageId);
if (result.success) {
if (result.data.status === 'delivered') return result.data;
if (result.data.status === 'failed') throw new Error(result.data.errorMessage);
}
await new Promise(r => setTimeout(r, 2000 * (i + 1)));
}
return null;
}
// Usage
listMessages({ status: 'delivered', limit: 10 })
.then(result => console.log(`Found ${result.pagination.total} delivered messages`));
getMessage(12345)
.then(result => console.log(`Message status: ${result.data.status}`));

Message API requests share the same rate limits as other API endpoints:

PlanPer-Minute Limit
Starter100
Marketer300
EnterpriseCustom