Cliqtel
  • Numbers
  • Trunks
  • Messaging
  • Connect
  • Pricing
  • Coverage
  • Help
🇬🇧 EN 🇳🇱 NL 🇩🇪 DE 🇫🇷 FR 🇪🇸 ES 🇧🇷 PT 🇸🇦 AR 🇨🇳 ZH 🇯🇵 JA 🇮🇳 HI
Sign in Sign up free Obtener un Número
← Help Center
On this page
Authentication Base URL Send SMS List Messages Get Message List Numbers Delivery Webhooks Error Handling Rate Limits Code Examples

SMS API Reference

Developer Docs · 12 min read REST API SMS Bearer Auth
Quick start: Create an API key in your portal, then send your first SMS with a single API call. Messages are charged per-segment from your wallet balance. Inbound SMS is free.

Authentication

All API requests require a Bearer token in the Authorization header. Create an API key from the API Keys page in your portal.

AUTHORIZATION HEADER
Authorization: Bearer YOUR_API_KEY
Keep your API key secret. Do not expose it in client-side code, public repositories, or URLs. If compromised, revoke it immediately from the portal and create a new one.

Base URL

https://cliqtel.com/api/v1/sms

Send SMS

POST /messages

Send an outbound SMS message from one of your SMS-enabled numbers.

Request body

ParameterTypeRequiredDescription
fromstringYes*Your SMS-enabled number in E.164 format (e.g. +16625163513)
from_number_idintegerYes*Alternatively, the numeric ID of your number (from GET /numbers)
tostringYesDestination number in E.164 format (e.g. +31612345678)
bodystringYesMessage text, max 1,600 characters
status_callback_urlstringNoURL to receive delivery status webhooks

* Provide either from or from_number_id, not both.

CURL
curl -X POST https://cliqtel.com/api/v1/sms/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+16625163513",
    "to": "+31612345678",
    "body": "Your order #1234 has shipped!"
  }'
RESPONSE (201 CREATED)
{
  "data": {
    "id": 42,
    "from": "+16625163513",
    "to": "+31612345678",
    "body": "Your order #1234 has shipped!",
    "direction": "outbound",
    "status": "queued",
    "segments": 1,
    "cost": 0.008,
    "currency": "EUR",
    "carrier": "didfarm",
    "created_at": "2026-04-03T10:15:30+00:00"
  }
}

List Messages

GET /messages

Retrieve your SMS messages with optional filtering and pagination.

Query parameters

ParameterTypeDescription
directionstringFilter by inbound or outbound
statusstringFilter by status: queued, sent, delivered, failed
number_idintegerFilter by DID number ID
fromstringFilter by sender number
tostringFilter by destination number
sincedatetimeOnly messages after this timestamp (ISO 8601)
pageintegerPage number (default: 1)
per_pageintegerResults per page (default: 25, max: 100)
CURL
curl https://cliqtel.com/api/v1/sms/messages?direction=outbound&per_page=10 \
  -H "Authorization: Bearer YOUR_API_KEY"
RESPONSE
{
  "data": [
    {
      "id": 42,
      "from": "+16625163513",
      "to": "+31612345678",
      "body": "Your order #1234 has shipped!",
      "direction": "outbound",
      "status": "delivered",
      "segments": 1,
      "cost": 0.008,
      "currency": "EUR",
      "carrier": "didfarm",
      "created_at": "2026-04-03T10:15:30+00:00"
    }
  ],
  "meta": {
    "total": 156,
    "page": 1,
    "per_page": 10,
    "total_pages": 16
  }
}

Get Message

GET /messages/{'{id}'}

Retrieve a single message by ID, including delivery status and cost.

CURL
curl https://cliqtel.com/api/v1/sms/messages/42 \
  -H "Authorization: Bearer YOUR_API_KEY"

List SMS Numbers

GET /numbers

List your active numbers that have SMS enabled. Use the id field as from_number_id when sending.

CURL
curl https://cliqtel.com/api/v1/sms/numbers \
  -H "Authorization: Bearer YOUR_API_KEY"
RESPONSE
{
  "data": [
    { "id": 11, "number": "+16625163513", "country_code": "US", "number_type": "local", "sms_enabled": true },
    { "id": 6, "number": "+16315950406", "country_code": "US", "number_type": "local", "sms_enabled": true }
  ]
}

Delivery Status Webhooks

Receive real-time delivery updates by providing a status_callback_url when sending a message.

SEND WITH CALLBACK
curl -X POST https://cliqtel.com/api/v1/sms/messages \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "+16625163513",
    "to": "+31612345678",
    "body": "Hello!",
    "status_callback_url": "https://yourapp.com/webhooks/sms"
  }'

Cliqtel will POST to your URL when the message status changes:

WEBHOOK PAYLOAD
{
  "event": "sms.status_updated",
  "data": {
    "id": 42,
    "from": "+16625163513",
    "to": "+31612345678",
    "direction": "outbound",
    "status": "delivered",
    "segments": 1,
    "cost": 0.008,
    "currency": "EUR",
    "created_at": "2026-04-03T10:15:30+00:00",
    "updated_at": "2026-04-03T10:15:33+00:00"
  },
  "timestamp": "2026-04-03T10:15:33+00:00"
}

Verifying webhook signatures

Each webhook includes an X-Cliqtel-Signature header containing an HMAC-SHA256 signature of the JSON payload, signed with your application key.

VERIFY SIGNATURE (NODE.JS)
const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Error Handling

All errors return a JSON object with an error key:

{
  "error": {
    "code": "insufficient_balance",
    "message": "Wallet balance too low to send this message"
  }
}
HTTP StatusError CodeDescription
401unauthenticatedMissing or invalid API key
404not_foundMessage or number not found
422number_not_foundFrom number not found, inactive, or SMS not enabled
422validation_errorMissing or invalid request parameters
429rate_limitedToo many requests (see Rate Limits)
500send_failedCarrier rejected the message

Rate Limits

LimitValue
Requests per minute60
Messages per second10 (carrier limit)

Rate limit headers are included in every response:

  • X-RateLimit-Limit — maximum requests allowed
  • X-RateLimit-Remaining — requests remaining in window
  • Retry-After — seconds to wait (only on 429 responses)

Code Examples

Node.js

SEND SMS WITH NODE.JS (FETCH)
const API_KEY = 'your_api_key_here';

async function sendSms(from, to, body) {
  const res = await fetch('https://cliqtel.com/api/v1/sms/messages', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ from, to, body }),
  });

  const data = await res.json();
  if (!res.ok) throw new Error(data.error?.message || 'Send failed');
  return data.data;
}

// Usage
const msg = await sendSms('+16625163513', '+31612345678', 'Hello!');
console.log(`Sent! ID: ${msg.id}, Status: ${msg.status}`);

Python

SEND SMS WITH PYTHON (REQUESTS)
import requests

API_KEY = 'your_api_key_here'
BASE_URL = 'https://cliqtel.com/api/v1/sms'

def send_sms(from_number, to, body):
    resp = requests.post(
        f'{BASE_URL}/messages',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json',
        },
        json={'from': from_number, 'to': to, 'body': body},
    )
    resp.raise_for_status()
    return resp.json()['data']

# Usage
msg = send_sms('+16625163513', '+31612345678', 'Hello from Python!')
print(f"Sent! ID: {msg['id']}, Status: {msg['status']}")

PHP

SEND SMS WITH PHP (CURL)
$apiKey = 'your_api_key_here';

$ch = curl_init('https://cliqtel.com/api/v1/sms/messages');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        "Authorization: Bearer {$apiKey}",
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'from' => '+16625163513',
        'to'   => '+31612345678',
        'body' => 'Hello from PHP!',
    ]),
]);

$response = curl_exec($ch);
$data = json_decode($response, true);
echo "Sent! ID: {$data['data']['id']}\n";

Webhook receiver (Node.js / Express)

RECEIVE DELIVERY WEBHOOKS
const express = require('express');
const app = express();
app.use(express.json());

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

  if (event === 'sms.status_updated') {
    console.log(`Message ${data.id}: ${data.status}`);

    if (data.status === 'delivered') {
      // Message confirmed delivered
    } else if (data.status === 'failed') {
      // Handle delivery failure
    }
  }

  res.sendStatus(200);
});

app.listen(3000);

Ready to integrate?

Create an API key and send your first SMS in under a minute.

Get API key →
© 2026 Cliqtel · cliqtel.com
About Blog Partners Coverage API Docs Status Privacy Terms Cookies Help Search
cliqtel.com is operated by Cliqtel B.V., registered in Zeist, the Netherlands · KVK 42033793 · VAT NL865150076B01 · SBI 62.09

We use essential cookies to make Cliqtel work. With your consent, we also use analytics cookies to improve our service. Cookie Policy