Additional plugins and connectors

Telegram bot

Deploy the open-source MakePay Telegram shop bot with hosted checkout, authenticated webhooks, durable orders, and payment reconciliation.

Accept crypto payments in a Telegram bot

Overview

The MakePay Telegram Bot is an open-source, production-minded starter for selling products from a Telegram bot and accepting cryptocurrency through MakePay hosted checkout. Version 1.0.0 is released under the MIT license.

The bot presents a product catalog in a private Telegram chat, creates an idempotent MakePay payment link, and sends the buyer to MakePay's hosted checkout. Signed MakePay webhooks update a durable local order, while a background reconciliation worker recovers status changes if a webhook is delayed or missed.

The starter accepts payments but deliberately does not fulfill products. Connect your own idempotent fulfillment only after the local order reaches the paid state.

The service exposes four HTTP routes:

RoutePurpose
GET /healthzProcess liveness
GET /readyzDatabase and Telegram readiness
POST /webhooks/telegramAuthenticated Telegram updates
POST /webhooks/makepaySigned MakePay payment events

Before you start

You need:

  • Python 3.12 or newer, or Docker with Docker Compose;
  • a Telegram bot token created with @BotFather;
  • a MakeCrypto company with MakePay settlement assets and addresses configured;
  • a MakePay API key ID and secret;
  • a public HTTPS origin that routes to the bot service; and
  • a MakePay webhook signing secret.

The service uses SQLite by default. Run one application replica and mount the data directory on persistent storage. See Production and scaling before adding replicas.

Create credentials

Telegram

Open @BotFather, create a bot with /newbot, and save the token as TELEGRAM_BOT_TOKEN.

Generate a separate random secret for Telegram webhook authentication:

openssl rand -hex 32

Save this value as TELEGRAM_WEBHOOK_SECRET. It may contain only letters, numbers, _, and -.

MakePay

In MakeCrypto:

  1. Select the company that should receive the bot's payments.
  2. Open Integrations > API Integrations and create a dedicated MakePay API key.
  3. Save its key ID and secret as MAKEPAY_KEY_ID and MAKEPAY_KEY_SECRET.
  4. Open Merchant > Payment settings and rotate or copy the webhook secret.
  5. Save that value separately as MAKEPAY_WEBHOOK_SECRET.

The API key secret and webhook secret are shown only when they are created or rotated. Store them in your deployment platform's secret manager. For the credential and rotation model, see API authentication.

Install with Docker

Clone the released source and create the environment file:

git clone --branch v1.0.0 https://github.com/makepay-io/makepay-telegram-bot.git
cd makepay-telegram-bot
cp .env.example .env

Configure .env:

TELEGRAM_BOT_TOKEN=<BotFather token>
TELEGRAM_WEBHOOK_SECRET=<random Telegram webhook secret>
PUBLIC_BASE_URL=https://bot.example.com

MAKEPAY_KEY_ID=<MakePay API key ID>
MAKEPAY_KEY_SECRET=<MakePay API key secret>
MAKEPAY_WEBHOOK_SECRET=<MakePay webhook signing secret>

DATABASE_PATH=./data/bot.db
CATALOG_PATH=./catalog.json
RECONCILE_INTERVAL_SECONDS=60
NOTIFICATION_INTERVAL_SECONDS=10
LOG_LEVEL=INFO

PUBLIC_BASE_URL must be a public HTTPS origin without a trailing slash. Plain HTTP is accepted only for local development when the host is localhost and ALLOW_INSECURE_LOCALHOST=true.

Build and start the service:

docker compose up --build -d
docker compose logs -f

The application registers its Telegram webhook during startup. Check the service before continuing:

curl --fail https://bot.example.com/healthz
curl --fail https://bot.example.com/readyz

For development without Docker, follow the repository README.

Configure the catalog

Edit catalog.json before starting the bot:

[
  {
    "id": "coffee",
    "name": "Coffee voucher",
    "description": "A demo voucher fulfilled by the merchant after payment.",
    "amount": "5.00",
    "fiatCurrency": "USD"
  }
]

Each item must follow these rules:

  • id is 1–32 lowercase letters, numbers, _, or -;
  • amount is a positive decimal string with at most two decimal places; and
  • fiatCurrency is a three-letter ISO currency code.

The MakePay company configuration controls the accepted settlement assets, networks, and destination addresses. Restart the service after changing the catalog.

Configure webhooks

The public origin produces two webhook URLs:

https://bot.example.com/webhooks/telegram
https://bot.example.com/webhooks/makepay

The application registers the Telegram URL and TELEGRAM_WEBHOOK_SECRET automatically. In MakeCrypto, set the MakePay company callback URL to:

https://bot.example.com/webhooks/makepay

The signing secret configured there must exactly match MAKEPAY_WEBHOOK_SECRET.

The two webhook secrets are independent:

  • Telegram sends TELEGRAM_WEBHOOK_SECRET in x-telegram-bot-api-secret-token.
  • MakePay signs the timestamp and exact raw request body with HMAC-SHA256 and sends the result in x-makepay-signature.

Do not reuse either secret as the MakePay API key secret. See Webhooks for the signing format, delivery attempts, and payment event model.

Test the payment flow

  1. Open the bot in a private Telegram chat.
  2. Send /shop and select a low-value catalog item.
  3. Confirm the bot opens a hosted makepay.io checkout URL.
  4. Complete the payment.
  5. Confirm the bot reports the paid status and /orders shows the updated order once.
  6. Confirm the MakeCrypto webhook request log shows a successful delivery.

Payment-link creation is idempotent, so Telegram retries cannot create duplicate checkout links. Webhook events are deduplicated, a paid order never downgrades, and the reconciliation worker polls MakePay for incomplete orders when an event is delayed.

Test the complete refund, support, and fulfillment journey before taking live orders. Rotate test credentials when switching to production.

Production and scaling

For a single replica:

  • mount /app/data on durable storage and back it up;
  • terminate TLS at a trusted ingress and forward traffic only to the service port;
  • keep GET /healthz available for liveness and GET /readyz for readiness;
  • restrict secret access to the service identity;
  • use a dedicated MakePay API key for this bot; and
  • connect idempotent fulfillment to the local paid transition.

SQLite is intentionally the default for a simple self-hosted deployment. Do not run multiple replicas against the same SQLite file. Before scaling out, move orders, webhook deduplication, and the notification outbox to PostgreSQL and use row-level work claiming.

Pin the production deployment to a reviewed release or commit. Review v1.0.0 and the repository's architecture notes before extending the worker or persistence model.

Security model

The starter is designed so the Telegram bot never receives cryptocurrency, seed phrases, or private keys. Buyers leave Telegram for MakePay hosted checkout, and payment state changes only after server-side verification.

Keep these boundaries:

  • never expose MakePay keys or webhook secrets in Telegram messages, client code, logs, or the catalog;
  • keep Telegram and MakePay webhook authentication enabled;
  • preserve exact raw-body verification for MakePay events;
  • do not log checkout URLs, webhook payloads, Telegram user IDs, or secrets;
  • apply request-size limits at both the ingress and application;
  • acknowledge unknown signed events without treating them as paid; and
  • make fulfillment idempotent by the local order and MakePay payment UID.

Read the repository security policy before reporting a vulnerability or changing the trust boundaries.

Troubleshooting

The bot does not respond

Check /readyz and the application logs. Confirm PUBLIC_BASE_URL is reachable over HTTPS, the BotFather token is correct, and the Telegram webhook secret contains only supported characters. The CLI command makepay-telegram-bot set-telegram-webhook can register the webhook again.

Checkout creation returns an authentication error

Confirm MAKEPAY_KEY_ID and MAKEPAY_KEY_SECRET belong to the same MakeCrypto company and have not been rotated. Verify the deployment can reach https://www.makecrypto.io.

Payment succeeds but the order does not update

Compare the company callback URL with /webhooks/makepay, verify the deployed MAKEPAY_WEBHOOK_SECRET, and inspect the MakeCrypto webhook request log. MakePay signature verification uses the exact raw body and a five-minute timestamp tolerance, so also confirm the server clock is synchronized.

Duplicate events or notifications appear

Duplicate webhook delivery is normal in retry-safe payment flows. Keep the SQLite data volume persistent and do not run multiple replicas. Custom fulfillment must be idempotent even when the same paid state is observed more than once.

Need partner setup help?

Open the payment link details view in MakeCrypto to copy the generated snippets for a real payment UID, or return to the portal to manage merchant settings.

Open portal