Plans from ₹99 a monthFree HTTPS on every site18% GST invoice with your GSTIN for input tax creditFull refund within 7 days of your first paymentPay yearly, get 2 months freeNo auto-renewal, everPlans from ₹99 a monthFree HTTPS on every site18% GST invoice with your GSTIN for input tax creditFull refund within 7 days of your first paymentPay yearly, get 2 months freeNo auto-renewal, ever

Python apps

Example: a daily price alert

Build a job that checks a price list every morning at 09:30 IST and sends you a Telegram message when prices change.

Intermediate20 min readUpdated 27 October 2026
On this page

In this tutorial you build price-bot, a job that runs every day at 09:30 IST. It downloads a price list over HTTPS, compares it with yesterday's prices saved in the app folder, and sends you a Telegram message listing what changed. It uses only things apps are allowed to do: outbound HTTPS and files in its own folder (it uses Telegram rather than email; to send email instead, see Send email from your website or app).

Before you start#

  • A plan with a free Python app slot (Pro and above, or any Compute plan). See Run Python apps from the panel.
  • The Telegram app on your phone or computer.
  • A URL that returns your prices as JSON. In this example the feed looks like this; replace it with your supplier's or your own shop's feed:
JSON
[
  {"sku": "DRL-500", "name": "Drill 500 W", "price": 2499},
  {"sku": "SAW-210", "name": "Circular saw", "price": 5890}
]

Step 1: Create a Telegram bot and find your chat id#

  1. Open Telegram and message @BotFather. Send /newbot, choose a name and a user name ending in bot.
  2. Copy the token BotFather gives you. It looks like 123456789:AAH.... Treat it like a password.
  3. Send any message to your new bot (open it and press Start). The bot can only message you after you have messaged it.
  4. Find your chat id. Open https://api.telegram.org/bot<TOKEN>/getUpdates in your browser, with your token in place of <TOKEN>. In the reply, find "chat":{"id":123456789 and copy the number.

Step 2: Write the code on your computer#

Make a folder called price-bot with three files.

requirements.txt

Text
requests==2.32.3

config.json (your own values)

JSON
{
  "feed_url": "https://shop.acme.in/prices.json",
  "telegram_token": "123456789:AAH-your-token",
  "chat_id": "123456789"
}

main.py

Python
"""price-bot: compare today's prices with the last run and send changes to Telegram."""
import json
import sys
from pathlib import Path

import requests

HERE = Path(__file__).resolve().parent
CONFIG = json.loads((HERE / "config.json").read_text(encoding="utf-8"))
STATE = HERE / "prices.json"          # saved between runs, in the app folder


def fetch_prices() -> dict:
    r = requests.get(CONFIG["feed_url"], timeout=30)
    r.raise_for_status()
    return {item["sku"]: {"name": item["name"], "price": item["price"]} for item in r.json()}


def load_previous() -> dict:
    if STATE.exists():
        return json.loads(STATE.read_text(encoding="utf-8"))
    return {}


def send_telegram(text: str) -> None:
    url = f"https://api.telegram.org/bot{CONFIG['telegram_token']}/sendMessage"
    r = requests.post(url, data={"chat_id": CONFIG["chat_id"], "text": text}, timeout=30)
    r.raise_for_status()


def main() -> int:
    today = fetch_prices()
    before = load_previous()
    print(f"fetched {len(today)} prices")

    changes = []
    for sku, item in sorted(today.items()):
        old = before.get(sku)
        if old is None:
            changes.append(f"NEW {item['name']}: Rs {item['price']}")
        elif old["price"] != item["price"]:
            arrow = "up" if item["price"] > old["price"] else "down"
            changes.append(f"{item['name']}: Rs {old['price']} -> Rs {item['price']} ({arrow})")

    if changes:
        send_telegram("Price changes today:\n" + "\n".join(changes))
        print(f"{len(changes)} change(s), Telegram alert sent")
    else:
        print("no changes")

    # Save only after the alert went out, so a failed send is retried tomorrow.
    STATE.write_text(json.dumps(today, indent=2), encoding="utf-8")
    return 0


if __name__ == "__main__":
    try:
        sys.exit(main())
    except requests.RequestException as e:
        print(f"network error: {e}", file=sys.stderr)
        sys.exit(1)

The script exits with code 1 on a network error, so the run shows as failed in the panel and you notice.

Step 3: Create the app in the panel#

  1. Open Python apps and go to Create an app.
  2. Enter App name price-bot, keep Entry file main.py.
  3. Choose Mode: Job: runs, then stops.
  4. Choose Schedule: Daily at a time (IST) and set Daily time (IST) to 09:30.
  5. Press Create app.

Step 4: Upload the code#

  1. Zip the folder. On Windows right-click price-bot → Send to → Compressed (zipped) folder. On macOS right-click → Compress. The zip may contain the price-bot folder itself: FiniteHost removes that single top folder, so main.py lands in /apps/price-bot.
  2. Drop price-bot.zip on the Upload code box of the app's card.
  3. Wait a minute for "uploaded. It lands in the app folder within a minute."

You can also copy the three files over SFTP into /apps/price-bot. See Connect with SFTP.

Step 5: Test with Run now#

  1. Press Run now. The panel says the server starts it within 30 seconds.
  2. Press the refresh button on the card after 30 seconds. The first run also installs requests, so give it a minute or two.
  3. Open Logs. You should see lines like Installing requirements.txt, fetched 2 prices and 2 change(s), Telegram alert sent, and Last run finished with exit 0.
  4. Check Telegram for the message.

Step 6: Turn on the schedule#

  1. Press Enable schedule. The card now shows the next run, for example next Wed 2026-10-28 09:30 IST.
  2. Check Cron jobs the next morning: the Recent runs table shows each day's result.

Troubleshooting tips#

  • network error: 401 or 404 from Telegram: the token is wrong, or has a space in it.
  • 400 Bad Request: chat not found: wrong chat id, or you never pressed Start in the bot chat.
  • FileNotFoundError: config.json: the file is not in /apps/price-bot. Check with SFTP; maybe the zip had two levels of folders.
  • KeyError: 'sku': your feed uses different field names. Change them in fetch_prices().
  • The job failed at 09:30 but works with Run now: the feed was down at that moment. The next day's run tries again.

What's next#

Was this helpful?

Still stuck?

Email support@finitehost.com with your subscription ID (it starts with t, shown on the panel's Dashboard) and what you tried. A person replies, usually within one business day.

Last updated 27 October 2026. Found something wrong? Tell support@finitehost.com.