Telenoda for developers RUOpen web version
Mini apps

Mini apps

Web interfaces inside Telenoda: stores, forms, services. Signed user data, theme and cloud storage.

What it is

A mini app is your web page that opens on top of the chat with a bot. The user doesn't need to install anything or sign in: Telenoda passes the page signed data about the user and the chat, the color theme and the window size.

Suitable for stores, appointment booking, forms, personal dashboards and games. The app runs in an isolated window with no access to the account or Telenoda data.

Domains

First, specify the app's domains in “My bots” — up to 10 per bot. Telenoda will only open an https:// address on one of these domains or their subdomains. IP addresses, internal zones and Telenoda domains can't be specified. If the domains change, buttons with old addresses stop opening.

Launch methods

SourceWhat the app receivesHow to return a result
A web_app button under a messageinitData with query_idthe bot's server calls answerWebAppQuery, and the message is sent to the chat from the user “via bot”
Menu buttoninitData with query_idanswerWebAppQuery
A web_app button in a keyboard instead of the system oneinitData without query_idTelenoda.WebApp.sendData — once, up to 4096 bytes; the bot receives message.web_app_data
A ?startapp= link and the attachment menuinitData with start_paramanswerWebAppQuery

On the first launch of a bot's app, Telenoda asks the user for permission.

Setup

Include the bridge script in the page's <head> before your own scripts. It creates the window.Telenoda.WebApp object.

<script src="https://web.telenoda.org/clouchat-web-app.js"></script>
<script>
  const app = window.Telenoda.WebApp;
  app.ready();
  app.expand();
  document.body.style.background = app.themeParams.bg_color || "#ffffff";

  app.MainButton.setText("Place order");
  app.MainButton.onClick(async () => {
    app.MainButton.showProgress();
    await fetch("/api/order", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ initData: app.initData, items: cart }),
    });
    app.close();
  });
  app.MainButton.show();
</script>

Launch data validation

initData is a query string with the fields query_id, user, chat_type, chat_instance, start_param, auth_date and the signature hash. Ready-made launch data validators from bot libraries work without changes.

Don't trust initDataUnsafe on the server. Send the whole initData string to your server and verify the signature with the bot token.

import hashlib
import hmac
import time
from urllib.parse import parse_qsl


def check_init_data(init_data: str, token: str, max_age: int = 3600) -> dict:
    fields = dict(parse_qsl(init_data, strict_parsing=True))
    received = fields.pop("hash", "")
    check_string = "\n".join(f"{key}={value}" for key, value in sorted(fields.items()))
    secret = hmac.new(b"WebAppData", token.encode(), hashlib.sha256).digest()
    expected = hmac.new(secret, check_string.encode(), hashlib.sha256).hexdigest()
    if not hmac.compare_digest(expected, received):
        raise PermissionError("bad signature")
    if time.time() - int(fields["auth_date"]) > max_age:
        raise PermissionError("init data expired")
    return fields

The verification key is the HMAC-SHA256 of the bot token with the key "WebAppData"; the signature is the HMAC-SHA256 of the string of sorted key=value pairs joined by line breaks.

The Telenoda.WebApp object

Field or methodPurpose
initData, initDataUnsafelaunch data: a string for the server and a parsed object for the interface
version, platform, isVersionAtLeast()bridge version and client platform
themeParams, colorSchemeTelenoda theme colors and the light or dark scheme
ready(), expand(), close()ready, expand to full height, close
MainButtonmain button at the bottom: setText, show, hide, enable, disable, showProgress, setParams, onClick
BackButton“Back” button in the header: show, hide, onClick
HapticFeedbackimpactOccurred, notificationOccurred, selectionChanged
CloudStoragekey–value storage per user and bot
sendData()send data to the bot (launch from a keyboard)
openLink(), openTelenodaLink()open an external link in the browser or a me.telenoda.org link in Telenoda
showPopup(), showAlert(), showConfirm()system dialogs, up to three buttons
requestContact()ask the user to share their phone number
setHeaderColor(), setBackgroundColor()header and window background colors
enableClosingConfirmation()confirm before closing
requestFullscreen(), exitFullscreen(), safeAreaInset, contentSafeAreaInsetfull-screen mode and safe area insets
addToHomeScreen(), checkHomeScreenStatus()app shortcut on the home screen
onEvent(), offEvent()event subscription

Events

themeChanged, viewportChanged, mainButtonClicked, backButtonClicked, popupClosed, contactRequested, fullscreenChanged, fullscreenFailed, safeAreaChanged, contentSafeAreaChanged, homeScreenAdded, homeScreenFailed, homeScreenChecked.

Theme

Telenoda passes the current theme colors in themeParams in #rrggbb format: bg_color, secondary_bg_color, text_color, hint_color, link_color, button_color, button_text_color, header_bg_color, bottom_bar_bg_color, accent_text_color, section_bg_color, section_header_text_color, subtitle_text_color, destructive_text_color, section_separator_color. When the theme changes, themeChanged fires.

CloudStorage

Up to 1024 keys per user and bot. A key is 1–128 characters A-Z a-z 0-9 _ -, a value is up to 4096 characters. The storage is available after the user has launched the bot's mini app.

const storage = window.Telenoda.WebApp.CloudStorage;
storage.setItem("theme", "dark", (error, saved) => {
  if (error) return console.warn(error);
  storage.getItem("theme", (error, value) => console.log(value));
});

Methods: setItem, getItem, getItems, removeItem, removeItems, getKeys.

Security

  • Validate initData on your server with every request and limit its age by auth_date.
  • Don't keep the bot token in the page code: do everything that requires the token on the server.
  • Recalculate prices, stock and permissions on the server without trusting data from the page.
  • If the app processes personal data, publish your own data processing policy.

The Bot API methods for mini apps — answerWebAppQuery and setChatMenuButton — are described in the reference.