Skip to content

وثائق API

نظرة عامة

تتيح واجهة BotBell API لبرامجك ونصوصك البرمجية إرسال إشعارات فورية إلى أجهزة Apple الخاصة بك واستقبال الردود. لا حاجة لـ SDK — فقط طلبات HTTP بسيطة.

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

كيف يعمل

  1. أنشئ بوتاً في تطبيق BotBell وانسخ رابط الإرسال الخاص به
  2. أرسل رسالة JSON عبر POST إلى رابط الإرسال من أي لغة أو أداة
  3. استلم إشعاراً فورياً على جميع أجهزتك
  4. اختيارياً، استقبل ردودك عبر رد اتصال عنوان URL للرد أو API الاستطلاع

صيغة الاستجابة

جميع استجابات API تستخدم نفس غلاف JSON. الرمز 0 يعني النجاح؛ أي رمز آخر يشير إلى خطأ.

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

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

إرسال رسالة

أرسل إشعاراً من بوتك إلى تطبيق BotBell. رابط الإرسال الخاص ببوتك يحتوي بالفعل على توكن المصادقة — فقط أرسل POST إليه.

نقطة النهاية

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

لا حاجة لترويسة Authorization. التوكن في الرابط هو مصادقتك.

يمكنك أيضاً استخدام 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 إذا تم إرسال الإشعار إلى APNs بنجاح؛ false إذا لم يكن هناك جهاز مسجّل
timestampطابع زمني Unix (بالثواني) عند إنشاء الرسالة

جرّب الآن

الصق رمز البوت الخاص بك وأرسل إشعارًا فوريًا حقيقيًا إلى جهازك.


استقبال الردود

عندما ترد على بوت في التطبيق، يمكن لـ BotBell توجيه ردك إلى خادمك تلقائياً. هذا اختياري — تحتاجه فقط إذا كان بوتك يتعامل مع محادثات ثنائية الاتجاه.

إعداد عنوان URL للرد

في تطبيق BotBell، انتقل إلى إعدادات بوتك وأدخل عنوان URL للرد (مثلاً https://your-server.com/botbell/reply). سيرسل BotBell ردودك إلى هذا العنوان عبر POST فور حدوثها.

حمولة رد الاتصال

عندما ترد، يرسل 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فشل التحقق من الطلب (مثلاً حقل الرسالة مفقود أو الجسم كبير جداً)
40029429تم تجاوز حد المعدل — طلبات كثيرة جداً في الدقيقة
40030429تم استنفاد حصة الرسائل الشهرية
40031403تم الوصول إلى حد البوتات لخطتك
50000500خطأ داخلي في الخادم

حدود المعدل والحصص

الحدالقيمة
معدل الإرسال (لكل بوت)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),
  );
}