Docs para desarrolladores
Español

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 GET como POST.
  • Hay cuatro formas de enviar los parámetros: cadena de consulta (?chat_id=1&text=hi), application/x-www-form-urlencoded, application/json y, 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_codeCuándoEjemplos de description
400Un parámetro es incorrectoBad 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
401El token es incorrectoUnauthorized
403No hay permiso para enviarForbidden: bot can't initiate conversation with a user, Forbidden: bot is not a member of the group chat
404Método o archivo inexistenteNot Found: method not found
409getUpdates con un webhook configuradoConflict: can't use getUpdates method while webhook is active; use deleteWebhook to delete the webhook first
413El cuerpo supera los 12 MBRequest Entity Too Large
500Error interno del servidorInternal 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ámetroTipoObligatorioDescripción
offsetIntegerOpcionalSolo las actualizaciones con este número o superior. Las anteriores se borran como «recibidas». Pasa el último update_id + 1 que procesaste.
limitIntegerOpcionalDe 1 a 100, 100 por defecto
timeoutIntegerOpcionalSegundos de espera, de 0 a 50, 0 por defecto. Se recomienda entre 25 y 30.
allowed_updatesArray of StringSe ignoraSe 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ámetroTipoObligatorioDescripción
urlStringDirección pública https://. Una cadena vacía elimina el webhook
secret_tokenStringOpcionalDe 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_updatesArray of StringOpcionalEntre message, edited_message y callback_query. Si se deja vacío, todos
drop_pending_updatesBooleanOpcionalDescarta las actualizaciones pendientes
max_connectionsIntegerOpcionalDe 1 a 100, 40 por defecto. Solo se guarda; la entrega es de una en una por bot
certificateInputFileNo admitido400: usa un certificado público
ip_addressStringSe ignora

Devuelve: True

deleteWebhook

POST/bot<token>/deleteWebhook

Elimina el webhook y vuelve a getUpdates. Tiene éxito aunque no haya webhook.

ParámetroTipoObligatorioDescripción
drop_pending_updatesBooleanOpcionalDescarta 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étodoQué hace
getMeInformación del propio bot
sendMessageEnviar texto (con botones)
sendPhotoEnviar una foto
editMessageTextEditar el texto y los botones de un mensaje enviado
editMessageCaptionEditar el pie de una foto
editMessageReplyMarkupEditar solo los botones
deleteMessageBorrar un mensaje
answerCallbackQueryResponder a la pulsación de un botón
sendChatActionIndicador «escribiendo» (solo se acepta)
getChatInformación de un chat
getFileRuta de descarga de una foto recibida
setMyCommands · getMyCommands · deleteMyCommandsMenú de comandos
logOut · closePor compatibilidad (no hacen nada)
getUpdates · setWebhook · deleteWebhook · getWebhookInfoRecibir actualizaciones (arriba)
Qué se puede poner en 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ámetroTipoObligatorioDescripción
chat_idInteger o StringChat de destino (ver el recuadro de arriba)
textStringDe 1 a 4.096 caracteres. Se envía tal cual
reply_markupInlineKeyboardMarkup · ReplyKeyboardMarkup · ReplyKeyboardRemove · ForceReplyOpcionalBotones
disable_notificationBooleanOpcionalEnviar sin sonido
parse_mode, entities, reply_parameters, link_preview_optionsSe ignoraSe 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ámetroTipoObligatorioDescripción
chat_idInteger o StringChat de destino
photoInputFile o StringUn 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
captionStringOpcionalDe 0 a 1.024 caracteres
reply_markupIgual que en sendMessageOpcional
disable_notificationBooleanOpcional

Devuelve: el Message enviado (con un file_id nuevo en photo)

editMessageText

POST/bot<token>/editMessageText

ParámetroTipoObligatorioDescripción
chat_idInteger o StringChat en el que está el mensaje
message_idIntegerMensaje que se edita (uno enviado por el bot)
textStringTexto nuevo, de 1 a 4.096 caracteres
reply_markupInlineKeyboardMarkupOpcionalBotones nuevos. Si lo omites, los botones desaparecen (igual que en Telegram)
inline_message_idStringNo admitidoNo 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ámetroTipoObligatorioDescripción
callback_query_idStringEl callback_query.id de la actualización
textStringOpcionalTexto que aparece un momento sobre la pantalla
show_alertBooleanOpcionalCon true, se muestra en un cuadro con botón de confirmación
urlStringOpcionalDirección que abrirá la aplicación
cache_timeIntegerOpcionalSegundos 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ámetroTipoObligatorioDescripción
commandsArray of BotCommand100 como máximo
language_codeStringOpcionalSe guarda como lista de ese idioma. Por ahora la aplicación solo muestra la lista predeterminada, sin código de idioma
scopeBotCommandScopeSe 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.

CampoTipoDescripción
update_idIntegerNúmero que aumenta de 1 en 1. Se usa en el offset de getUpdates
message opcionalMessageMensaje 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 opcionalMessageMensaje editado
callback_query opcionalCallbackQueryPulsación de un botón inline

User

CampoTipoDescripción
idIntegerID de usuario (solo tiene sentido dentro de este servidor)
is_botBooleantrue si es un bot
first_nameStringNombre. En una cuenta eliminada, Deleted Account
last_name opcionalStringApellido
username opcionalStringNombre de usuario (sin @)

Chat

CampoTipoDescripción
idIntegerSi es una persona, su ID (positivo); si es un grupo básico, un número negativo
typeStringprivate o group
title opcionalStringNombre del grupo (group)
first_name, last_name, username opcionalStringNombre y nombre de usuario de la otra persona (private)

Message

CampoTipoDescripción
message_idIntegerNúmero del mensaje dentro de este chat
from opcionalUserRemitente
chatChatChat en el que está el mensaje
dateIntegerHora de envío (segundos Unix)
edit_date opcionalIntegerHora de la última edición
text opcionalStringTexto (siempre presente si no es un mensaje con foto)
entities opcionalArray of MessageEntityComandos, menciones, URL y hashtags del texto
photo opcionalArray of PhotoSizeFoto (en Pabal, un único elemento con el original)
caption opcionalStringPie de foto
caption_entities opcionalArray of MessageEntityComandos, menciones, URL y hashtags del pie de foto
reply_markup opcionalInlineKeyboardMarkupBotones inline que lleva el mensaje

MessageEntity

CampoTipoDescripción
typeStringbot_command, mention, url, hashtag
offsetIntegerPosición inicial (en unidades de código UTF-16)
lengthIntegerLongitud (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

CampoTipoDescripción
file_idStringID para descargar (getFile) y para volver a enviar (sendPhoto)
file_unique_idStringEl mismo valor para la misma foto, aunque sea otro bot. No sirve para descargar
width, heightIntegerTamaño en píxeles
file_sizeIntegerBytes

File

CampoTipoDescripción
file_id, file_unique_idStringIgual que en PhotoSize
file_sizeIntegerBytes
file_pathStringCon la forma photos/<file_id>.jpg. Se añade detrás de /file/bot<token>/ para descargar

CallbackQuery

CampoTipoDescripción
idStringID que se pasa a answerCallbackQuery
fromUserPersona que pulsó el botón
message opcionalMessageMensaje que lleva el botón
chat_instanceStringValor que identifica ese chat
data opcionalStringEl 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

CampoTipoDescripción
textStringTexto del botón
callback_data uno de los dosStringValor que se envía al bot al pulsar, de 1 a 64 bytes
url uno de los dosStringDirección que se abre al pulsar

Otros tipos como switch_inline_query, web_app, login_url o pay todavía no existen (400).

ReplyKeyboardMarkup

CampoTipoDescripción
keyboardArray of Array of KeyboardButtonPanel de botones bajo el campo de texto
resize_keyboard, one_time_keyboard, is_persistent, selective opcionalBooleanAjustar el tamaño · ocultar tras un uso · mostrar siempre · solo para ciertas personas
input_field_placeholder opcionalStringTexto 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

CampoTipoDescripción
commandStringDe 1 a 32 caracteres: letras latinas minúsculas, números y guion bajo (sin /)
descriptionStringDe 1 a 256 caracteres

WebhookInfo

CampoTipoDescripción
urlStringDirección del webhook; si no hay, una cadena vacía
has_custom_certificateBooleanSiempre false
pending_update_countIntegerNúmero de actualizaciones que esperan a ser entregadas
ip_address opcionalStringÚltima IP a la que se envió
last_error_date opcionalIntegerHora del último fallo (segundos Unix)
last_error_message opcionalStringMotivo del último fallo (lista)
max_connections opcionalIntegerEl valor que pasaste a setWebhook
allowed_updates opcionalArray of StringEl valor que pasaste a setWebhook

Diferencias con la Bot API de Telegram

  • Tipos de actualización: solo llegan message, edited_message y callback_query. No hay publicaciones de canal, consultas inline, pagos, encuestas, cambios de miembros (my_chat_member), etc.
  • Formato: parse_mode y entities se 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_connections solo 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 …) devuelven 404 Not Found: method not found.