Desarrollo de bots
Referencia de la Bot API
Todos los métodos que acepta la Bot API HTTP de Pabal, los objetos que intercambia y sus errores, sin omitir nada. Compatible con la Bot API de Telegram.
La Bot API HTTP de Pabal usa el mismo formato de direcciones, peticiones, respuestas y errores que la Bot API de Telegram. Este documento recoge solo lo que Pabal acepta de verdad. Los métodos que no aparecen aquí devuelven 404 Not Found: method not found. Si es tu primera vez, empieza por el tutorial para crear un bot.
Enviar peticiones
https://pabal.me/bot<token>/<método>
- Método HTTP: se admiten tanto
GETcomoPOST. - Hay cuatro formas de enviar los parámetros: cadena de consulta (
?chat_id=1&text=hi),application/x-www-form-urlencoded,application/jsony, cuando subes archivos,multipart/form-data. Se pueden combinar. - Los parámetros de tipo objeto (
reply_markup,commands,allowed_updates) van tal cual, como objeto o array, en un cuerpo JSON, y como cadena JSON en formularios y cadenas de consulta. - El nombre del método no distingue entre mayúsculas y minúsculas (
sendMessage=sendmessage). - El tamaño del cuerpo puede llegar a 12 MB (por encima,
413). - La descarga de archivos usa otra dirección:
https://pabal.me/file/bot<token>/<file_path>(getFile).
Respuestas y errores
La respuesta siempre es JSON. Si todo va bien, llega un HTTP 200 con result; si falla, llega el estado HTTP correspondiente, un error_code igual a ese estado y una description legible para personas.
{"ok": true, "result": { … }}{"ok": false, "error_code": 400, "description": "Bad Request: chat not found"}| error_code | Cuándo | Ejemplos de description |
|---|---|---|
400 | Un parámetro es incorrecto | Bad Request: chat not found, Bad Request: message text is empty, Bad Request: message is not modified: …, Bad Request: message to edit not found, Bad Request: wrong file identifier/HTTP URL specified, Bad Request: query is too old and response timeout expired or query ID is invalid |
401 | El token es incorrecto | Unauthorized |
403 | No hay permiso para enviar | Forbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat |
404 | Método o archivo inexistente | Not Found: method not found |
409 | getUpdates con un webhook configurado | Conflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first |
413 | El cuerpo supera los 12 MB | Request Entity Too Large |
500 | Error interno del servidor | Internal Server Error |
Pabal todavía no aplica límites de frecuencia de peticiones (429 Too Many Requests), pero podría hacerlo en el futuro: prepara tu código para que, si recibe un 429, espere parameters.retry_after segundos antes de volver a enviar.
Recibir actualizaciones
Se usa uno de estos dos modos. No se pueden usar los dos a la vez.
getUpdates
POST/bot<token>/getUpdates
Recoge las actualizaciones pendientes (long polling). Si hay un webhook configurado, 409.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
offset | Integer | Opcional | Solo las actualizaciones con este número o superior. Las anteriores se borran como «recibidas». Pasa el último update_id + 1 que procesaste. |
limit | Integer | Opcional | De 1 a 100, 100 por defecto |
timeout | Integer | Opcional | Segundos de espera, de 0 a 50, 0 por defecto. Se recomienda entre 25 y 30. |
allowed_updates | Array of String | Se ignora | Se acepta pero no se usa. Para filtrar por tipo, filtra después de recibir. |
Devuelve: Array of Update
setWebhook
POST/bot<token>/setWebhook
Recibe las actualizaciones en una dirección HTTPS. La explicación detallada está en el documento Webhooks.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
url | String | Sí | Dirección pública https://. Una cadena vacía elimina el webhook |
secret_token | String | Opcional | De 1 a 256 caracteres, A-Z a-z 0-9 _ -. Se envía en la cabecera de la petición X-Telegram-Bot-Api-Secret-Token |
allowed_updates | Array of String | Opcional | Entre message, edited_message y callback_query. Si se deja vacío, todos |
drop_pending_updates | Boolean | Opcional | Descarta las actualizaciones pendientes |
max_connections | Integer | Opcional | De 1 a 100, 40 por defecto. Solo se guarda; la entrega es de una en una por bot |
certificate | InputFile | No admitido | 400: usa un certificado público |
ip_address | String | Se ignora |
Devuelve: True
deleteWebhook
POST/bot<token>/deleteWebhook
Elimina el webhook y vuelve a getUpdates. Tiene éxito aunque no haya webhook.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
drop_pending_updates | Boolean | Opcional | Descarta las actualizaciones pendientes |
Devuelve: True
getWebhookInfo
GET/bot<token>/getWebhookInfo
Estado del webhook. Sin parámetros. Si no hay webhook, url es una cadena vacía.
Devuelve: WebhookInfo
Métodos
| Método | Qué hace |
|---|---|
getMe | Información del propio bot |
sendMessage | Enviar texto (con botones) |
sendPhoto | Enviar una foto |
editMessageText | Editar el texto y los botones de un mensaje enviado |
editMessageCaption | Editar el pie de una foto |
editMessageReplyMarkup | Editar solo los botones |
deleteMessage | Borrar un mensaje |
answerCallbackQuery | Responder a la pulsación de un botón |
sendChatAction | Indicador «escribiendo» (solo se acepta) |
getChat | Información de un chat |
getFile | Ruta de descarga de una foto recibida |
setMyCommands · getMyCommands · deleteMyCommands | Menú de comandos |
logOut · close | Por compatibilidad (no hacen nada) |
getUpdates · setWebhook · deleteWebhook · getWebhookInfo | Recibir actualizaciones (arriba) |
chat_id
En un chat uno a uno, el ID de la persona (positivo); en un grupo básico, el ID del grupo (negativo); o bien el nombre de usuario de la persona ("@hana_lee"). Todos se pueden obtener del chat.id de las actualizaciones. Los IDs de canales y supergrupos (-100…) todavía no existen (400 chat not found).
getMe
GET/bot<token>/getMe
Sirve para comprobar que el token es correcto. Sin parámetros.
Devuelve: User. En el caso de un bot se añaden can_join_groups (true), can_read_all_group_messages (true), supports_inline_queries (false), can_connect_to_business (false) y has_main_web_app (false).
sendMessage
POST/bot<token>/sendMessage
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
chat_id | Integer o String | Sí | Chat de destino (ver el recuadro de arriba) |
text | String | Sí | De 1 a 4.096 caracteres. Se envía tal cual |
reply_markup | InlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReply | Opcional | Botones |
disable_notification | Boolean | Opcional | Enviar sin sonido |
parse_mode, entities, reply_parameters, link_preview_options … | Se ignora | Se aceptan pero no se usan. No se aplica ningún formato |
Devuelve: el Message enviado
Para escribir a una persona, esa persona tiene que haber escrito antes al bot (403 Forbidden: bot can't initiate conversation with a user). Para escribir en un grupo, el bot tiene que ser miembro de ese grupo.
sendPhoto
POST/bot<token>/sendPhoto
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
chat_id | Integer o String | Sí | Chat de destino |
photo | InputFile o String | Sí | Un archivo subido como multipart/form-data (hasta 10 MB; JPEG, PNG o GIF) o el file_id de una foto recibida antes. Las URL todavía no se admiten |
caption | String | Opcional | De 0 a 1.024 caracteres |
reply_markup | Igual que en sendMessage | Opcional | |
disable_notification | Boolean | Opcional |
Devuelve: el Message enviado (con un file_id nuevo en photo)
editMessageText
POST/bot<token>/editMessageText
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
chat_id | Integer o String | Sí | Chat en el que está el mensaje |
message_id | Integer | Sí | Mensaje que se edita (uno enviado por el bot) |
text | String | Sí | Texto nuevo, de 1 a 4.096 caracteres |
reply_markup | InlineKeyboardMarkup | Opcional | Botones nuevos. Si lo omites, los botones desaparecen (igual que en Telegram) |
inline_message_id | String | No admitido | No hay modo inline, así que 400 |
Devuelve: el Message editado. El cambio se refleja al instante en la aplicación, y los mensajes que edita una persona le llegan al bot como edited_message.
Si el texto y los botones son idénticos a los anteriores, 400 Bad Request: message is not modified: …; si intentas editar un mensaje ajeno, 400 Bad Request: message can't be edited.
editMessageCaption
POST/bot<token>/editMessageCaption
Parámetros: chat_id, message_id, caption (de 0 a 1.024 caracteres; si lo omites, se borra el pie) y reply_markup. Devuelve: el Message editado.
editMessageReplyMarkup
POST/bot<token>/editMessageReplyMarkup
Deja el texto como está y cambia solo los botones. Parámetros: chat_id, message_id y reply_markup (si lo omites, se borran los botones). Devuelve: el Message editado.
deleteMessage
POST/bot<token>/deleteMessage
Parámetros: chat_id y message_id. Borra el mensaje para ambas partes del chat. Si el mensaje no existe, 400 Bad Request: message to delete not found. Devuelve: True.
answerCallbackQuery
POST/bot<token>/answerCallbackQuery
Responde a un botón pulsado por una persona (CallbackQuery). Solo se puede responder en menos de 10 segundos y una sola vez.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
callback_query_id | String | Sí | El callback_query.id de la actualización |
text | String | Opcional | Texto que aparece un momento sobre la pantalla |
show_alert | Boolean | Opcional | Con true, se muestra en un cuadro con botón de confirmación |
url | String | Opcional | Dirección que abrirá la aplicación |
cache_time | Integer | Opcional | Segundos que la aplicación recordará esta respuesta |
Devuelve: True. Si es demasiado tarde o ya se respondió, 400 Bad Request: query is too old and response timeout expired or query ID is invalid.
sendChatAction
POST/bot<token>/sendChatAction
Se acepta por compatibilidad y devuelve True, pero por ahora la aplicación no muestra «escribiendo…».
getChat
GET/bot<token>/getChat?chat_id=…
Parámetro: chat_id (numérico). Si es una persona, esa persona; si es un grupo, solo los grupos de los que el bot es miembro. Devuelve: Chat. Si no existe o no se puede ver, 400 Bad Request: chat not found.
getFile
GET/bot<token>/getFile?file_id=…
Obtiene la ruta de descarga de una foto recibida a partir de su file_id. Devuelve: File. Después se descarga desde esta dirección.
https://pabal.me/file/bot<token>/<file_path>
El file_id es también el derecho a obtener esa foto. Si el valor no es válido, 400 Bad Request: wrong file identifier/HTTP URL specified.
setMyCommands
POST/bot<token>/setMyCommands
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
commands | Array of BotCommand | Sí | 100 como máximo |
language_code | String | Opcional | Se guarda como lista de ese idioma. Por ahora la aplicación solo muestra la lista predeterminada, sin código de idioma |
scope | BotCommandScope | Se ignora |
Devuelve: True. Si un comando no cumple las reglas, 400 Bad Request: BOT_COMMAND_INVALID.
getMyCommands
GET/bot<token>/getMyCommands
Parámetro: language_code (opcional). Devuelve: Array of BotCommand.
deleteMyCommands
POST/bot<token>/deleteMyCommands
Parámetro: language_code (opcional). Vacía esa lista. Devuelve: True.
logOut · close
En Telegram son métodos que se usan al pasar a un servidor local de la Bot API. En Pabal no hay adónde pasar, así que solo se aceptan y devuelven True. Para invalidar un token, usa /revoke de BotFather.
Objetos
opcional junto a un campo significa que puede no aparecer. Pabal no envía los demás campos de Telegram que no figuran aquí.
Update
Una novedad. Contiene update_id y uno de los tres campos siguientes.
| Campo | Tipo | Descripción |
|---|---|---|
update_id | Integer | Número que aumenta de 1 en 1. Se usa en el offset de getUpdates |
message opcional | Message | Mensaje nuevo para el bot (en un chat uno a uno, o todos los mensajes de los grupos de los que el bot es miembro) |
edited_message opcional | Message | Mensaje editado |
callback_query opcional | CallbackQuery | Pulsación de un botón inline |
User
| Campo | Tipo | Descripción |
|---|---|---|
id | Integer | ID de usuario (solo tiene sentido dentro de este servidor) |
is_bot | Boolean | true si es un bot |
first_name | String | Nombre. En una cuenta eliminada, Deleted Account |
last_name opcional | String | Apellido |
username opcional | String | Nombre de usuario (sin @) |
Chat
| Campo | Tipo | Descripción |
|---|---|---|
id | Integer | Si es una persona, su ID (positivo); si es un grupo básico, un número negativo |
type | String | private o group |
title opcional | String | Nombre del grupo (group) |
first_name, last_name, username opcional | String | Nombre y nombre de usuario de la otra persona (private) |
Message
| Campo | Tipo | Descripción |
|---|---|---|
message_id | Integer | Número del mensaje dentro de este chat |
from opcional | User | Remitente |
chat | Chat | Chat en el que está el mensaje |
date | Integer | Hora de envío (segundos Unix) |
edit_date opcional | Integer | Hora de la última edición |
text opcional | String | Texto (siempre presente si no es un mensaje con foto) |
entities opcional | Array of MessageEntity | Comandos, menciones, URL y hashtags del texto |
photo opcional | Array of PhotoSize | Foto (en Pabal, un único elemento con el original) |
caption opcional | String | Pie de foto |
caption_entities opcional | Array of MessageEntity | Comandos, menciones, URL y hashtags del pie de foto |
reply_markup opcional | InlineKeyboardMarkup | Botones inline que lleva el mensaje |
MessageEntity
| Campo | Tipo | Descripción |
|---|---|---|
type | String | bot_command, mention, url, hashtag |
offset | Integer | Posición inicial (en unidades de código UTF-16) |
length | Integer | Longitud (en unidades de código UTF-16) |
El servidor las detecta en el texto y las añade automáticamente. Todavía no hay entidades de formato como negrita o cursiva.
PhotoSize
| Campo | Tipo | Descripción |
|---|---|---|
file_id | String | ID para descargar (getFile) y para volver a enviar (sendPhoto) |
file_unique_id | String | El mismo valor para la misma foto, aunque sea otro bot. No sirve para descargar |
width, height | Integer | Tamaño en píxeles |
file_size | Integer | Bytes |
File
| Campo | Tipo | Descripción |
|---|---|---|
file_id, file_unique_id | String | Igual que en PhotoSize |
file_size | Integer | Bytes |
file_path | String | Con la forma photos/<file_id>.jpg. Se añade detrás de /file/bot<token>/ para descargar |
CallbackQuery
| Campo | Tipo | Descripción |
|---|---|---|
id | String | ID que se pasa a answerCallbackQuery |
from | User | Persona que pulsó el botón |
message opcional | Message | Mensaje que lleva el botón |
chat_instance | String | Valor que identifica ese chat |
data opcional | String | El callback_data del botón |
InlineKeyboardMarkup
inline_keyboard: Array of Array of InlineKeyboardButton. El array exterior son las filas y cada array interior, los botones de una fila. Como máximo 100 filas y 100 botones por mensaje.
InlineKeyboardButton
| Campo | Tipo | Descripción |
|---|---|---|
text | String | Texto del botón |
callback_data uno de los dos | String | Valor que se envía al bot al pulsar, de 1 a 64 bytes |
url uno de los dos | String | Dirección que se abre al pulsar |
Otros tipos como switch_inline_query, web_app, login_url o pay todavía no existen (400).
ReplyKeyboardMarkup
| Campo | Tipo | Descripción |
|---|---|---|
keyboard | Array of Array of KeyboardButton | Panel de botones bajo el campo de texto |
resize_keyboard, one_time_keyboard, is_persistent, selective opcional | Boolean | Ajustar el tamaño · ocultar tras un uso · mostrar siempre · solo para ciertas personas |
input_field_placeholder opcional | String | Texto de ayuda en el campo de texto |
KeyboardButton
Una cadena, o un objeto con text y los campos opcionales request_contact (enviar mi contacto) y request_location (enviar mi ubicación), de tipo Boolean.
ReplyKeyboardRemove
{"remove_keyboard": true}: oculta el panel de botones. selective es opcional.
ForceReply
{"force_reply": true}: la aplicación abre el campo de texto en modo de respuesta a este mensaje. selective e input_field_placeholder son opcionales.
BotCommand
| Campo | Tipo | Descripción |
|---|---|---|
command | String | De 1 a 32 caracteres: letras latinas minúsculas, números y guion bajo (sin /) |
description | String | De 1 a 256 caracteres |
WebhookInfo
| Campo | Tipo | Descripción |
|---|---|---|
url | String | Dirección del webhook; si no hay, una cadena vacía |
has_custom_certificate | Boolean | Siempre false |
pending_update_count | Integer | Número de actualizaciones que esperan a ser entregadas |
ip_address opcional | String | Última IP a la que se envió |
last_error_date opcional | Integer | Hora del último fallo (segundos Unix) |
last_error_message opcional | String | Motivo del último fallo (lista) |
max_connections opcional | Integer | El valor que pasaste a setWebhook |
allowed_updates opcional | Array of String | El valor que pasaste a setWebhook |
Diferencias con la Bot API de Telegram
- Tipos de actualización: solo llegan
message,edited_messageycallback_query. No hay publicaciones de canal, consultas inline, pagos, encuestas, cambios de miembros (my_chat_member), etc. - Formato:
parse_modeyentitiesse ignoran y el texto se envía tal cual. Solo los comandos, las menciones, las URL y los hashtags se marcan automáticamente. - Tipos de chat: solo chats uno a uno y grupos básicos. No hay canales, supergrupos ni temas de foro.
- Multimedia: solo fotos. No hay documentos, vídeos, voz, stickers, álbumes ni envío mediante URL.
- Bots en grupos: no hay modo de privacidad, así que reciben todos los mensajes del grupo.
- Cola: las actualizaciones no recogidas se guardan en memoria, hasta las 1.000 más recientes por bot, y se pierden al reiniciar el servidor (Telegram las conserva 24 horas).
- Webhooks: las actualizaciones se envían de una en una y en orden (
max_connectionssolo se guarda), no se aceptan certificados autofirmados y no hay restricción de puerto. - IDs: los IDs de usuario, de mensaje y de archivo solo tienen sentido dentro de este servidor. Como no hay canales ni supergrupos, tampoco hay IDs con la forma
-100…. - Métodos inexistentes: los que no están en la lista de arriba (
forwardMessage,copyMessage,sendDocument,sendPoll,getChatMember,banChatMember,answerInlineQuery…) devuelven404 Not Found: method not found.