Skip to content

Документация API

Обзор

API BotBell позволяет вашим программам и скриптам отправлять push-уведомления на устройства Apple и получать ответы. SDK не требуется — только простые HTTP-запросы.

Base URL: https://api.botbell.app

Как это работает

  1. Создайте бота в приложении BotBell и скопируйте его URL для push-сообщений
  2. Отправьте JSON-сообщение POST-запросом на URL для push-сообщений из любого языка или инструмента
  3. Получите мгновенное push-уведомление на всех ваших устройствах
  4. При необходимости получайте ваши ответы через URL обратного вызова или API опроса

Формат ответа

Все ответы API используют единую JSON-обёртку. Код 0 означает успех; любой другой код указывает на ошибку.

// Success
{
  "code": 0,
  "message": "success",
  "data": { ... }
}

// Error
{
  "code": 40001,
  "message": "Invalid bot token"
}

Отправить сообщение

Отправьте уведомление от вашего бота в приложение BotBell. URL для push-сообщений вашего бота уже содержит токен аутентификации — просто отправьте POST-запрос.

Конечная точка

POST https://api.botbell.app/v1/push/<your_bot_token>

Заголовок Authorization не требуется. Токен в URL является вашей аутентификацией.

Также вы можете использовать POST /v1/messages/push с заголовком X-Bot-Token: <token>.

Тело запроса (JSON)

ПолеТипОбязательноОписание
messagestringДаТекст сообщения (макс. 4 096 символов)
titlestringНетЗаголовок, отображаемый над сообщением (макс. 256 символов)
urlstringНетНажимаемая ссылка, прикреплённая к уведомлению
imageUrlstringНетURL изображения для отображения в уведомлении

Пример запроса

curl
curl -X POST https://api.botbell.app/v1/push/bt_your_token \
  -H "Content-Type: application/json" \
  -d '{
    "message": "Server CPU is at 95%!",
    "title": "Alert",
    "url": "https://grafana.example.com/dashboard"
  }'

Ответ

{
  "code": 0,
  "message": "success",
  "data": {
    "message_id": "msg_abc123",
    "delivered": true,
    "timestamp": 1709827200
  }
}
ПолеОписание
message_idУникальный идентификатор этого сообщения
deliveredtrue, если push-уведомление было успешно отправлено в APNs; false, если нет зарегистрированного устройства
timestampUnix-метка времени (секунды) создания сообщения

Попробовать сейчас

Вставьте токен вашего бота и отправьте реальное push-уведомление на ваше устройство.


Получение ответов

Когда вы отвечаете боту в приложении, BotBell может автоматически переслать ваш ответ на ваш сервер. Это опционально — вам это нужно только если ваш бот поддерживает двустороннюю переписку.

Настройка URL обратного вызова

В приложении BotBell перейдите в настройки бота и введите URL обратного вызова (например, https://your-server.com/botbell/reply). BotBell будет отправлять POST-запросы с вашими ответами на этот URL по мере их поступления.

Полезная нагрузка обратного вызова

Когда вы отвечаете, BotBell отправляет POST-запрос на ваш URL обратного вызова в следующем формате:

POST https://your-server.com/botbell/reply
Headers:
  Content-Type: application/json
  X-Webhook-Signature: sha256=abc123...
  X-Webhook-Timestamp: 1709827300

Body:
{
  "event": "user_reply",
  "bot_id": "bot_abc123",
  "message_id": "msg_xyz789",
  "content": "Got it, thanks!",
  "timestamp": 1709827300
}

Проверка подписи

Каждый обратный вызов включает подпись HMAC-SHA256, чтобы вы могли убедиться, что он пришёл от BotBell. Ключом подписи является секрет Webhook, указанный в настройках вашего бота.

signature = HMAC-SHA256(
  key:     <your_webhook_secret>,
  message: "<timestamp>.<raw_request_body>"
)

Для проверки подписи:

  1. Извлеките заголовки X-Webhook-Timestamp и X-Webhook-Signature
  2. Убедитесь, что временная метка не старше 5 минут (для защиты от атак повторного воспроизведения)
  3. Вычислите HMAC-SHA256 от строки "<timestamp>.<raw_body>", используя секрет Webhook в качестве ключа
  4. Сравните вычисленное значение с подписью после префикса "sha256="

Ответ вашего сервера

Верните любой HTTP-код 2xx для подтверждения получения. Ответы с кодом, отличным от 2xx, или тайм-ауты (5 секунд) считаются ошибками — ответ будет сохранён в очереди опроса на 24 часа, чтобы вы могли получить его позже.


Опрос ответов

Если у вас нет публичного сервера для приёма обратных вызовов, вы можете получать ответы через опрос. Это также полезно в качестве запасного варианта, когда ваш URL обратного вызова временно недоступен.

Конечная точка

GET https://api.botbell.app/v1/messages/poll
Headers:
  X-Bot-Token: <your_bot_token>

Параметры запроса

ПолеТипПо умолчаниюОписание
sinceinteger-Возвращать только сообщения после указанной Unix-метки времени
limitinteger20Количество возвращаемых сообщений (макс. 100)

Ответ

{
  "code": 0,
  "message": "success",
  "data": {
    "messages": [
      {
        "message_id": "msg_xyz789",
        "content": "Got it, thanks!",
        "timestamp": 1709827300
      }
    ],
    "has_more": false
  }
}

Примечание: Опрошенные сообщения помечаются как прочитанные и не будут возвращены повторно. Неопрошенные сообщения истекают через 24 часа.


Коды ошибок

КодHTTP-статусОписание
40001401Неверный или отсутствующий токен бота
40010400Ошибка валидации запроса (например, отсутствует поле message, тело слишком большое)
40029429Превышен лимит запросов — слишком много запросов в минуту
40030429Исчерпана месячная квота сообщений
40031403Достигнут лимит ботов для вашего тарифа
50000500Внутренняя ошибка сервера

Ограничения и квоты

ОграничениеЗначение
Частота push (на бота)60
Тело сообщения (символы)4,096
Заголовок (символы)256
Бесплатная месячная квота300 сообщений / бот
Хранение сообщений опроса24h
Тайм-аут URL обратного вызова5s

Статус ограничений возвращается в заголовках ответа:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1709827260

Примеры кода

Отправка сообщений

curl
curl -X POST https://api.botbell.app/v1/push/bt_your_token \
  -H "Content-Type: application/json" \
  -d '{"message":"Server CPU at 95%","title":"Alert"}'
Python
import requests

resp = requests.post(
    "https://api.botbell.app/v1/push/bt_your_token",
    json={
        "message": "Build #42 succeeded",
        "title": "CI/CD",
        "url": "https://ci.example.com/builds/42",
    },
)
print(resp.json())  # {"code": 0, "data": {"message_id": "...", ...}}
JavaScript / Node.js
const resp = await fetch("https://api.botbell.app/v1/push/bt_your_token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    message: "New order received!",
    title: "E-Commerce",
  }),
});
const data = await resp.json();
console.log(data);
Go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"
)

func main() {
    body, _ := json.Marshal(map[string]string{
        "message": "Disk usage above 90%",
        "title":   "Alert",
    })
    http.Post(
        "https://api.botbell.app/v1/push/bt_your_token",
        "application/json",
        bytes.NewReader(body),
    )
}
PHP
<?php
$ch = curl_init('https://api.botbell.app/v1/push/bt_your_token');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode([
        'message' => 'Payment received: $49.99',
        'title' => 'Stripe',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);

Проверка подписи ответов

Python
import hmac, hashlib

def verify_signature(payload: bytes, timestamp: str, signature: str, secret: str) -> bool:
    message = f"{timestamp}.{payload.decode()}"
    expected = hmac.new(secret.encode(), message.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)
Node.js
const crypto = require("crypto");

function verifySignature(payload, timestamp, signature, secret) {
  const message = `${timestamp}.${payload}`;
  const expected = crypto.createHmac("sha256", secret).update(message).digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(`sha256=${expected}`),
    Buffer.from(signature),
  );
}