Skip to content

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.app

Cómo Funciona

  1. Crea un bot en la app BotBell y copia su URL de push
  2. Envía un POST con un mensaje JSON a la URL de push desde cualquier lenguaje o herramienta
  3. Recibe una notificación push instantánea en todos tus dispositivos
  4. 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)

CampoTipoRequeridoDescripción
messagestringEl texto del mensaje (máx. 4,096 caracteres)
titlestringNoTítulo mostrado encima del mensaje (máx. 256 caracteres)
urlstringNoUn enlace táctil adjunto a la notificación
imageUrlstringNoURL de una imagen para mostrar en la notificación

Solicitud de Ejemplo

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

Respuesta

{
  "code": 0,
  "message": "success",
  "data": {
    "message_id": "msg_abc123",
    "delivered": true,
    "timestamp": 1709827200
  }
}
CampoDescripción
message_idID único para este mensaje
deliveredtrue si la notificación push fue enviada a APNs con éxito; false si no hay un dispositivo registrado
timestampMarca 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:

  1. Extrae los encabezados X-Webhook-Timestamp y X-Webhook-Signature
  2. Comprueba que la marca de tiempo esté dentro de los 5 minutos respecto a la hora actual (para prevenir ataques de repetición)
  3. Calcula HMAC-SHA256 sobre la cadena "<timestamp>.<raw_body>" usando tu Secreto de Webhook como clave
  4. 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

CampoTipoPredeterminadoDescripción
sinceinteger-Solo devolver mensajes posteriores a esta marca de tiempo Unix
limitinteger20Nú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ódigoEstado HTTPDescripción
40001401Token de bot inválido o faltante
40010400Validación de solicitud fallida (ej. campo de mensaje faltante, cuerpo demasiado grande)
40029429Límite de velocidad excedido — demasiadas solicitudes por minuto
40030429Cuota mensual de mensajes agotada
40031403Límite de bots alcanzado para tu plan
50000500Error interno del servidor

Límites de Velocidad y Cuotas

LímiteValor
Tasa de push (por bot)60
Cuerpo del mensaje (caracteres)4,096
Título (caracteres)256
Cuota mensual gratuita300 mensajes / bot
Retención de mensajes de sondeo24h
Tiempo de espera de URL de respuesta5s

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: 1709827260

Ejemplos de Código

Enviar Mensajes

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

Verificar Firmas de Respuesta

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