Skip to content

Documentation de l'API

Présentation

L'API BotBell permet à vos programmes et scripts d'envoyer des notifications push vers vos appareils Apple et de recevoir des réponses. Aucun SDK nécessaire — de simples requêtes HTTP suffisent.

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

Comment ça Marche

  1. Créez un bot dans l'app BotBell et copiez son URL de push
  2. Envoyez un message JSON via POST à l'URL de push depuis n'importe quel langage ou outil
  3. Recevez une notification push instantanée sur tous vos appareils
  4. Optionnellement, recevez vos réponses via le callback d'URL de réponse ou l'API de sondage

Format de Réponse

Toutes les réponses de l'API utilisent la même enveloppe JSON. Un code de 0 signifie succès ; tout autre code indique une erreur.

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

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

Envoyer un Message

Envoyez une notification depuis votre bot vers l'app BotBell. L'URL de push de votre bot contient déjà le token d'authentification — il suffit de faire un POST.

Point d'accès

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

Aucun en-tête Authorization nécessaire. Le token dans l'URL sert d'authentification.

Vous pouvez aussi utiliser POST /v1/messages/push avec l'en-tête X-Bot-Token: <token>.

Corps de la Requête (JSON)

ChampTypeRequisDescription
messagestringOuiLe texte du message (max 4 096 caractères)
titlestringNonTitre affiché au-dessus du message (max 256 caractères)
urlstringNonUn lien cliquable attaché à la notification
imageUrlstringNonURL d'une image à afficher dans la notification

Exemple de Requête

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"
  }'

Réponse

{
  "code": 0,
  "message": "success",
  "data": {
    "message_id": "msg_abc123",
    "delivered": true,
    "timestamp": 1709827200
  }
}
ChampDescription
message_idIdentifiant unique de ce message
deliveredtrue si la notification push a été envoyée à APNs avec succès ; false si aucun appareil n'est enregistré
timestampHorodatage Unix (secondes) de la création du message

Essayer maintenant

Collez votre token de bot et envoyez une vraie notification push à votre appareil.


Recevoir des Réponses

Lorsque vous répondez à un bot dans l'app, BotBell peut transmettre votre réponse à votre serveur automatiquement. C'est optionnel — vous n'en avez besoin que si votre bot gère des conversations bidirectionnelles.

Configurer une URL de Réponse

Dans l'app BotBell, allez dans les paramètres de votre bot et entrez une URL de réponse (ex. https://your-server.com/botbell/reply). BotBell enverra vos réponses à cette URL au fur et à mesure.

Payload du Callback

Lorsque vous répondez, BotBell envoie une requête POST à votre URL de réponse avec le format suivant :

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
}

Vérification de la Signature

Chaque callback inclut une signature HMAC-SHA256 pour que vous puissiez vérifier qu'il provient de BotBell. La clé de signature est le Secret Webhook affiché dans les paramètres de votre bot.

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

Pour vérifier la signature :

  1. Extrayez les en-têtes X-Webhook-Timestamp et X-Webhook-Signature
  2. Vérifiez que l'horodatage est dans les 5 minutes de l'heure actuelle (pour prévenir les attaques par rejeu)
  3. Calculez le HMAC-SHA256 sur la chaîne "<timestamp>.<raw_body>" en utilisant votre Secret Webhook comme clé
  4. Comparez la valeur calculée avec la signature après le préfixe "sha256="

Réponse de Votre Serveur

Retournez n'importe quel code de statut HTTP 2xx pour accuser réception. Les réponses non-2xx ou les délais d'attente dépassés (5 secondes) sont considérés comme des échecs — la réponse sera stockée dans la file de sondage pendant 24 heures pour que vous puissiez la récupérer plus tard.


Sonder les Réponses

Si vous n'avez pas de serveur public pour recevoir les callbacks, vous pouvez sonder les réponses à la place. C'est aussi utile comme solution de repli lorsque votre URL de réponse est temporairement indisponible.

Point d'accès

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

Paramètres de Requête

ChampTypePar défautDescription
sinceinteger-Ne retourner que les messages après cet horodatage Unix
limitinteger20Nombre de messages à retourner (max 100)

Réponse

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

Note : Les messages sondés sont marqués comme lus et ne seront plus retournés. Les messages non sondés expirent après 24 heures.


Codes d'Erreur

CodeStatut HTTPDescription
40001401Token de bot invalide ou manquant
40010400Validation de la requête échouée (ex. champ message manquant, corps trop volumineux)
40029429Limite de débit dépassée — trop de requêtes par minute
40030429Quota mensuel de messages épuisé
40031403Limite de bots atteinte pour votre forfait
50000500Erreur interne du serveur

Limites de Débit et Quotas

LimiteValeur
Débit de push (par bot)60
Corps du message (caractères)4,096
Titre (caractères)256
Quota mensuel gratuit300 messages / bot
Rétention des messages sondés24h
Délai d'attente de l'URL de réponse5s

Le statut de la limite de débit est retourné dans les en-têtes de réponse :

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

Exemples de Code

Envoi de Messages

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);

Vérification des Signatures de Réponse

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),
  );
}