Към съдържанието

Проверка на статус на съобщение

Проследявайте статуса на доставка на вашите съобщения, използвайки крайната точка (endpoint) за проверка на статус.

Крайна точка (Endpoint)

GET /bat/message/{messageId}

Заявка

URL Параметри

Параметър Тип Задължителен Описание
messageId string Да Уникален идентификатор на съобщението от отговора при изпращане

Автентикация

Използвайте който и да е от трите метода за удостоверяване:

curl -X GET https://restapi.smsbat.com/bat/message/abc123def456 \
  -H "X-Authorization-Key: your-api-key"
curl -X GET https://restapi.smsbat.com/bat/message/abc123def456 \
  -u "username:password"
curl -X GET https://restapi.smsbat.com/bat/message/abc123def456 \
  -u "@:your-api-key"

Отговор (Response)

Основен отговор

{
  "messagelistId": 123456,
  "messageId": "abc123def456",
  "deliverystatus": "delivered",
  "partscount": 1,
  "cost": 0.05
}

Полета в отговора

Поле Тип Описание
messagelistId integer Идентификатор на партидата (Batch identifier)
messageId string Уникален идентификатор на съобщението
deliverystatus string Текущ статус на доставка
partscount integer Брой на частите на съобщението
cost number Цена на съобщението във валутни единици

Разширен отговор (с Fallback)

Когато има конфигуриран fallback (резервен канал), отговорът включва допълнителни полета:

{
  "messagelistId": 123456,
  "messageId": "abc123def456",
  "deliverystatus": "delivered",
  "partscount": 1,
  "cost": 0.05,
  "fallbacks": [
    {
      "type": "sms",
      "status": "not_used"
    }
  ],
  "extendedStatuses": {
    "viber": "delivered",
    "sms": "not_used"
  },
  "rate": 0.05,
  "rateAmount": 0.05,
  "rateCurrency": "USD",
  "billAmount": 0.05,
  "billCurrency": "USD"
}

Стойности на статуса на доставка

Статус Описание
scheduled Поставено на опашка за изпращане
processing В момента се изпраща
delivered Успешно доставено
undeliverable Доставката е неуспешна, съобщението е отхвърлено
permanenterror Премахнато от опашката: перманентна грешка

Жизнен цикъл на статуса

graph LR
    A[scheduled] --> B[processing]
    B --> C[delivered]
    B --> D[undeliverable]
    B --> E[permanenterror]

Планирано (Scheduled)

Съобщението е прието и поставено на опашка за доставка:

{
  "deliverystatus": "scheduled",
  "partscount": 1
}

В процес на обработка (Processing)

Съобщението в момента се изпраща към получателя:

{
  "deliverystatus": "processing",
  "partscount": 1
}

Доставено (Delivered)

Съобщението е успешно доставено до получателя:

{
  "deliverystatus": "delivered",
  "partscount": 1,
  "cost": 0.05
}

Недоставимо (Undeliverable)

Съобщението не може да бъде доставено (невалиден номер, мрежова грешка):

{
  "deliverystatus": "undeliverable",
  "partscount": 1,
  "cost": 0.00
}

Постоянна грешка (Permanent Error)

Съобщението е премахнато от опашката поради постоянни проблеми с доставката:

{
  "deliverystatus": "permanenterror",
  "partscount": 1,
  "cost": 0.00
}

Проверка на множество съобщения

Проверка на статуса за множество съобщения във вашето приложение:

// JavaScript пример
async function checkMessageStatuses(messageIds) {
  const statuses = await Promise.all(
    messageIds.map(async (messageId) => {
      const response = await fetch(
        `https://restapi.smsbat.com/bat/message/${messageId}`,
        {
          headers: {
            'X-Authorization-Key': 'your-api-key'
          }
        }
      );
      return response.json();
    })
  );

  return statuses;
}

// Употреба
const messageIds = ['abc123', 'def456', 'ghi789'];
const statuses = await checkMessageStatuses(messageIds);

statuses.forEach(status => {
  console.log(`Съобщение ${status.messageId}: ${status.deliverystatus}`);
});

Polling (Регулярно запитване) за актуализации на статуса

Задръжте (Poll) крайната точка за статус за проследяване на доставка:

// Заявка на всеки 5 секунди докато бъде доставено
async function waitForDelivery(messageId, maxAttempts = 12) {
  for (let i = 0; i < maxAttempts; i++) {
    const response = await fetch(
      `https://restapi.smsbat.com/bat/message/${messageId}`,
      {
        headers: { 'X-Authorization-Key': 'your-api-key' }
      }
    );

    const status = await response.json();

    if (status.deliverystatus === 'delivered') {
      return { success: true, status };
    }

    if (status.deliverystatus === 'undeliverable' ||
        status.deliverystatus === 'permanenterror') {
      return { success: false, status };
    }

    // Изчакване 5 секунди преди следващата проверка
    await new Promise(resolve => setTimeout(resolve, 5000));
  }

  // Изчакване на таймаут след 60 секунди
  return { success: false, timeout: true };
}

Webhook Алтернатива

Вместо polling, използвайте уебкък (webhooks) за актуализации на статуса в реално време:

POST https://your-server.com/webhook
{
  "messageId": "abc123def456",
  "deliverystatus": "delivered",
  "timestamp": "2025-01-23T10:30:00Z",
  "cost": 0.05
}

Свържете се с вашия акаунт мениджър, за да конфигурирате Webhook URL.

Примери за внедряване

Python

import requests
import time

def check_status(message_id, api_key):
    url = f"https://restapi.smsbat.com/bat/message/{message_id}"
    headers = {"X-Authorization-Key": api_key}

    response = requests.get(url, headers=headers)
    return response.json()

def wait_for_delivery(message_id, api_key, timeout=60):
    """Очаквайте доставка или таймаут"""
    start_time = time.time()

    while time.time() - start_time < timeout:
        status = check_status(message_id, api_key)

        if status['deliverystatus'] == 'delivered':
            return {'success': True, 'status': status}

        if status['deliverystatus'] in ['undeliverable', 'permanenterror']:
            return {'success': False, 'status': status}

        time.sleep(5)

    return {'success': False, 'timeout': True}

# Употреба
message_id = "abc123def456"
result = wait_for_delivery(message_id, "your-api-key")

if result['success']:
    print(f"Съобщението е доставено! Цена: {result['status']['cost']}")
else:
    print("Доставката на съобщението се провали или изтече таймаут")

PHP

<?php

function checkStatus($messageId, $apiKey) {
    $url = "https://restapi.smsbat.com/bat/message/" . $messageId;

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        "X-Authorization-Key: " . $apiKey
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    return json_decode($response, true);
}

function waitForDelivery($messageId, $apiKey, $timeout = 60) {
    $startTime = time();

    while (time() - $startTime < $timeout) {
        $status = checkStatus($messageId, $apiKey);

        if ($status['deliverystatus'] === 'delivered') {
            return ['success' => true, 'status' => $status];
        }

        if (in_array($status['deliverystatus'],
                    ['undeliverable', 'permanenterror'])) {
            return ['success' => false, 'status' => $status];
        }

        sleep(5);
    }

    return ['success' => false, 'timeout' => true];
}

// Употреба
$messageId = "abc123def456";
$result = waitForDelivery($messageId, "your-api-key");

if ($result['success']) {
    echo "Съобщението е доставено! Цена: " . $result['status']['cost'];
} else {
    echo "Доставката на съобщението се провали или изтече таймаут";
}

Node.js

const axios = require('axios');

async function checkStatus(messageId, apiKey) {
  const response = await axios.get(
    `https://restapi.smsbat.com/bat/message/${messageId}`,
    {
      headers: { 'X-Authorization-Key': apiKey }
    }
  );

  return response.data;
}

async function waitForDelivery(messageId, apiKey, timeout = 60000) {
  const startTime = Date.now();

  while (Date.now() - startTime < timeout) {
    const status = await checkStatus(messageId, apiKey);

    if (status.deliverystatus === 'delivered') {
      return { success: true, status };
    }

    if (['undeliverable', 'permanenterror'].includes(
      status.deliverystatus
    )) {
      return { success: false, status };
    }

    // Изчакване 5 секунди
    await new Promise(resolve => setTimeout(resolve, 5000));
  }

  return { success: false, timeout: true };
}

// Употреба
const messageId = 'abc123def456';
const result = await waitForDelivery(messageId, 'your-api-key');

if (result.success) {
  console.log(`Съобщението е доставено! Цена: ${result.status.cost}`);
} else {
  console.log('Доставката на съобщението се провали или изтече таймаут');
}

Добри практики

Честота на заявяване (Polling Frequency)

  • ✅ Изисквайте статус на всеки 5-10 секунди
  • ✅ Прилагайте експоненциално връщане (exponential backoff)
  • ✅ Задайте разумен таймаут (60-120 секунди)
  • ❌ Не изисквайте статуса повече от веднъж в секунда
  • ❌ Не чакайте за неопределено време (indefinitely)

Обработка на грешки

async function checkStatusWithRetry(messageId, apiKey, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(
        `https://restapi.smsbat.com/bat/message/${messageId}`,
        {
          headers: { 'X-Authorization-Key': apiKey }
        }
      );

      if (!response.ok) {
        throw new Error(`HTTP ${response.status}`);
      }

      return await response.json();
    } catch (error) {
      if (i === retries - 1) throw error;

      // Изчакайте преди повторен опит (експоненциално връщане)
      await new Promise(resolve =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

Кеширане

Кеширайте резултатите от статуса, за да намалите извикванията на API-то:

const statusCache = new Map();

async function getCachedStatus(messageId, apiKey, cacheTTL = 30000) {
  const cached = statusCache.get(messageId);

  if (cached && Date.now() - cached.timestamp < cacheTTL) {
    return cached.status;
  }

  const status = await checkStatus(messageId, apiKey);

  statusCache.set(messageId, {
    status,
    timestamp: Date.now()
  });

  return status;
}

Пакетна (Batch) обработка

Когато проверявате много съобщения, групирайте заявките:

async function checkBatchStatus(messageIds, apiKey, batchSize = 10) {
  const results = [];

  for (let i = 0; i < messageIds.length; i += batchSize) {
    const batch = messageIds.slice(i, i + batchSize);
    const batchResults = await Promise.all(
      batch.map(id => checkStatus(id, apiKey))
    );
    results.push(...batchResults);

    // Ограничение на заявките
    if (i + batchSize < messageIds.length) {
      await new Promise(resolve => setTimeout(resolve, 1000));
    }
  }

  return results;
}

Случаи на употреба (Use Cases)

Потвърждение на поръчка

Проследявайте доставката на съобщения за потвърждение на поръчка:

const orderMessage = await sendMessage({
  to: customer.phone,
  text: `Поръчка #${orderId} е потвърдена`
});

// Изчакайте за доставка
const result = await waitForDelivery(orderMessage.messageId, apiKey);

if (result.success) {
  await updateOrder(orderId, { notificationSent: true });
} else {
  await scheduleRetry(orderId);
}

Двуфакторно удостоверяване (2FA)

Проверете доставката на OTP(one time password) кода преди таймаут:

const otpMessage = await sendOTP(userPhone, otpCode);

// Изисквайте статус на доставката
const delivered = await waitForDelivery(
  otpMessage.messageId,
  apiKey,
  30 // 30 секунди таймаут
);

if (!delivered.success) {
  // Изпратете чрез алтернативен канал
  await sendEmailOTP(userEmail, otpCode);
}

Маркетингови кампании

Проследяване на процентите на доставка за съобщения за кампании:

const messageIds = await sendCampaign(recipientList);

// Проверете всички статуси след 5 минути
setTimeout(async () => {
  const statuses = await checkBatchStatus(messageIds, apiKey);

  const delivered = statuses.filter(s =>
    s.deliverystatus === 'delivered'
  ).length;

  console.log(`Процент на доставка: ${delivered / statuses.length * 100}%`);
}, 5 * 60 * 1000);

Следващи стъпки