Documentación de la API
Descripción General
La API de BotBell permite que tus programas y scripts envíen notificaciones push a tus dispositivos Apple y reciban respuestas. No se necesita SDK — solo solicitudes HTTP simples.
Base URL: https://api.botbell.appCómo Funciona
- Crea un bot en la app BotBell y copia su URL de push
- Envía un POST con un mensaje JSON a la URL de push desde cualquier lenguaje o herramienta
- Recibe una notificación push instantánea en todos tus dispositivos
- Opcionalmente, recibe tus respuestas mediante callback de URL de respuesta o API de sondeo
Formato de Respuesta
Todas las respuestas de la API usan el mismo formato JSON. Un código 0 significa éxito; cualquier otro código indica un error.
// Success
{
"code": 0,
"message": "success",
"data": { ... }
}
// Error
{
"code": 40001,
"message": "Invalid bot token"
}Enviar un Mensaje
Envía una notificación desde tu bot a la app BotBell. La URL de push de tu bot ya contiene el token de autenticación — solo haz POST.
Endpoint
POST https://api.botbell.app/v1/push/<your_bot_token>No se necesita encabezado de autorización. El token en la URL es tu autenticación.
También puedes usar POST /v1/messages/push con el encabezado X-Bot-Token: <token>.
Cuerpo de la Solicitud (JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
message | string | Sí | El texto del mensaje (máx. 4,096 caracteres) |
title | string | No | Título mostrado encima del mensaje (máx. 256 caracteres) |
url | string | No | Un enlace táctil adjunto a la notificación |
imageUrl | string | No | URL de una imagen para mostrar en la notificación |
Solicitud de Ejemplo
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"
}'Respuesta
{
"code": 0,
"message": "success",
"data": {
"message_id": "msg_abc123",
"delivered": true,
"timestamp": 1709827200
}
}| Campo | Descripción |
|---|---|
message_id | ID único para este mensaje |
delivered | true si la notificación push fue enviada a APNs con éxito; false si no hay un dispositivo registrado |
timestamp | Marca de tiempo Unix (segundos) de creación del mensaje |
Pruébalo ahora
Pega tu token de bot y envía una notificación push real a tu dispositivo.
Recibir Respuestas
Cuando respondes a un bot en la app, BotBell puede reenviar tu respuesta a tu servidor automáticamente. Esto es opcional — solo lo necesitas si tu bot maneja conversaciones bidireccionales.
Configurar una URL de Respuesta
En la app BotBell, ve a los ajustes de tu bot e introduce una URL de respuesta (ej. https://tu-servidor.com/botbell/reply). BotBell enviará tus respuestas a esta URL en tiempo real.
Payload del Callback
Cuando respondes, BotBell envía una solicitud POST a tu URL de respuesta con el siguiente formato:
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
}Verificación de Firma
Cada callback incluye una firma HMAC-SHA256 para que puedas verificar que proviene de BotBell. La clave de firma es el Secreto de Webhook que se muestra en los ajustes de tu bot.
signature = HMAC-SHA256(
key: <your_webhook_secret>,
message: "<timestamp>.<raw_request_body>"
)Para verificar la firma:
- Extrae los encabezados X-Webhook-Timestamp y X-Webhook-Signature
- Comprueba que la marca de tiempo esté dentro de los 5 minutos respecto a la hora actual (para prevenir ataques de repetición)
- Calcula HMAC-SHA256 sobre la cadena "<timestamp>.<raw_body>" usando tu Secreto de Webhook como clave
- Compara el valor calculado con la firma después del prefijo "sha256="
Respuesta de Tu Servidor
Devuelve cualquier código de estado HTTP 2xx para confirmar la recepción. Las respuestas no-2xx o los tiempos de espera agotados (5 segundos) se tratan como fallos — la respuesta se almacenará en la cola de sondeo durante 24 horas para que puedas recuperarla después.
Sondear Respuestas
Si no tienes un servidor público para recibir callbacks, puedes sondear las respuestas. Esto también es útil como respaldo cuando tu URL de respuesta está temporalmente caída.
Endpoint
GET https://api.botbell.app/v1/messages/poll
Headers:
X-Bot-Token: <your_bot_token>Parámetros de Consulta
| Campo | Tipo | Predeterminado | Descripción |
|---|---|---|---|
since | integer | - | Solo devolver mensajes posteriores a esta marca de tiempo Unix |
limit | integer | 20 | Número de mensajes a devolver (máx. 100) |
Respuesta
{
"code": 0,
"message": "success",
"data": {
"messages": [
{
"message_id": "msg_xyz789",
"content": "Got it, thanks!",
"timestamp": 1709827300
}
],
"has_more": false
}
}Nota: Los mensajes sondeados se marcan como leídos y no se devolverán de nuevo. Los mensajes no sondeados expiran después de 24 horas.
Códigos de Error
| Código | Estado HTTP | Descripción |
|---|---|---|
| 40001 | 401 | Token de bot inválido o faltante |
| 40010 | 400 | Validación de solicitud fallida (ej. campo de mensaje faltante, cuerpo demasiado grande) |
| 40029 | 429 | Límite de velocidad excedido — demasiadas solicitudes por minuto |
| 40030 | 429 | Cuota mensual de mensajes agotada |
| 40031 | 403 | Límite de bots alcanzado para tu plan |
| 50000 | 500 | Error interno del servidor |
Límites de Velocidad y Cuotas
| Límite | Valor |
|---|---|
| Tasa de push (por bot) | 60 |
| Cuerpo del mensaje (caracteres) | 4,096 |
| Título (caracteres) | 256 |
| Cuota mensual gratuita | 300 mensajes / bot |
| Retención de mensajes de sondeo | 24h |
| Tiempo de espera de URL de respuesta | 5s |
El estado del límite de velocidad se devuelve en los encabezados de respuesta:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1709827260Ejemplos de Código
Enviar Mensajes
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"}'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": "...", ...}}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);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
$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);Verificar Firmas de Respuesta
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)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),
);
}