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:
| Route | Purpose |
|---|---|
GET /healthz | Process liveness |
GET /readyz | Database and Telegram readiness |
POST /webhooks/telegram | Authenticated Telegram updates |
POST /webhooks/makepay | Signed 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:
- Select the company that should receive the bot's payments.
- Open Integrations > API Integrations and create a dedicated MakePay API key.
- Save its key ID and secret as
MAKEPAY_KEY_IDandMAKEPAY_KEY_SECRET. - Open Merchant > Payment settings and rotate or copy the webhook secret.
- 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:
idis 1–32 lowercase letters, numbers,_, or-;amountis a positive decimal string with at most two decimal places; andfiatCurrencyis 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_SECRETinx-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
- Open the bot in a private Telegram chat.
- Send
/shopand select a low-value catalog item. - Confirm the bot opens a hosted
makepay.iocheckout URL. - Complete the payment.
- Confirm the bot reports the paid status and
/ordersshows the updated order once. - 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/dataon durable storage and back it up; - terminate TLS at a trusted ingress and forward traffic only to the service port;
- keep
GET /healthzavailable for liveness andGET /readyzfor readiness; - restrict secret access to the service identity;
- use a dedicated MakePay API key for this bot; and
- connect idempotent fulfillment to the local
paidtransition.
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.