Telegram Bot Crypto Payments
Take crypto payments in a Telegram bot for subscriptions or access.
Open the interactive version or read this guide as markdown.
Tags: Telegram, Payments, Webhooks, Node.js
Paste this prompt into Claude, ChatGPT, or any AI tool. It works best with the CoinCircuit MCP server connected: https://mcp.coincircuit.io
You are helping me integrate CoinCircuit crypto payments into my existing Telegram bot. I have the CoinCircuit MCP server connected.
If you have access to the CoinCircuit MCP server, call these tools for the most accurate and detailed schema outputs:
- Call
get_api_overviewin the CoinCircuit MCP for base URLs, auth method, and available features. - Call
get_endpointwith methodpostand path/api/v1/paymentsfor the full payment session creation schema. - Call
search_apiwith querywebhookand typeschemasto list all webhook payload schemas. - Call
get_schemawith namePaymentCompletedWebhookDtofor the exact payment.completed webhook payload. - Call
get_schemawith nameTransactionReceivedWebhookDtofor the transaction.received webhook payload.
Use the live MCP data as your source of truth. The details below are a guide, but if the MCP returns something different, trust the MCP.
API Basics
- Base URL (production):
https://api.coincircuit.io - Base URL (sandbox):
https://sandbox-api.coincircuit.io - Auth: Pass your API key in the
x-api-keyheader on every request.
Project Context
I have an existing Telegram bot and I want to add crypto payment support using CoinCircuit. The integration should:
- Create a CoinCircuit payment session when a user wants to pay
- Send the hosted checkout URL to the user in chat
- Listen for payment confirmation via webhook
- Trigger the appropriate action in my bot (grant access, deliver content, activate subscription, etc.)
This pattern works for any Telegram bot use case: subscription access, one-time purchases, premium features, tip jars, or pay-per-use commands.
What I Need You to Implement
1. Create a payment session from a bot command
When a user triggers a payment (e.g. via a command or button callback), create a CoinCircuit payment session from your bot's backend:
Endpoint: POST /api/v1/payments
(Call get_endpoint with method post, path /api/v1/payments, section request in the CoinCircuit MCP for the exact request body schema.)
Required fields:
title(string) - e.g. "Premium Channel - 30 Days"description(string) - e.g. "Subscription payment for premium access"amount(string) - subscription price as a string, e.g."9.99"currency(string) -"USD"or"NGN"customer(object) - must includeemail(required). IncludetelegramIdfor linking.
Optional fields:
metadata(object) - storetelegramUserId,telegramUsername,plan,channelId,subscriptionPeriodEndfor webhook reconciliationsuccessUrl(string) - redirect after payment (HTTPS)cancelUrl(string) - redirect if cancelledwebhookUrl(string) - per-session webhook URL override (HTTPS)asset(string) - lock to a specific crypto:"BTC","ETH","USDT","USDC","SOL","BNB","TRX"chain(string) - lock to a specific blockchain:"bitcoin","ethereum","solana","bsc","tron","base","arbitrum"
Example request body:
{
"title": "Premium Channel - 30 Days",
"description": "Subscription payment for premium Telegram access",
"amount": "9.99",
"currency": "USD",
"customer": {
"email": "user@example.com",
"telegramId": "123456789"
},
"metadata": {
"telegramUserId": "123456789",
"telegramUsername": "johndoe",
"plan": "premium-monthly",
"channelId": "-1001234567890",
"subscriptionPeriodEnd": "2026-04-30T23:59:59.000Z"
},
"successUrl": "https://mybot.com/subscription/success"
}
Response (201): Returns a session object. Key fields:
data.reference- session reference (store this alongside the subscription)data.url- hosted checkout page URL. Send this to the user via Telegram.data.payment.status- starts as"pending"data.expiresAt- session expiration timestamp
(Call get_endpoint with method post, path /api/v1/payments, section success in the CoinCircuit MCP for the full response schema.)
2. Send checkout link to the user
After creating the session, send the data.url to the user in chat. The hosted checkout page handles crypto selection, address display, and payment detection automatically. No additional frontend work needed.
3. Webhook handler: process payment confirmation
Set up an endpoint to receive CoinCircuit webhooks. This is where your bot takes action after payment.
(Call get_schema with name PaymentCompletedWebhookDto in the CoinCircuit MCP for the full payload.)
Payment events (envelope: { event: string, data: { session: PaymentSession } }):
payment.completed- full payment confirmed. This is your trigger to take action in your bot.- Read
data.session.metadata.telegramUserIdto identify the user - Read
data.session.metadatafor any custom data you stored (plan, product, channel ID, etc.) - Execute your bot's logic: grant access, send a file, activate a feature, update a subscription, etc.
- Read
payment.expired- session expired before payment. Optionally notify the user and offer a new session.payment.partial- customer sent crypto but not enough. The session stays open for more payments.payment.underpaid- session closed with less than the required amount. Checkdata.session.payment.amountReceivedvsdata.session.payment.amount. Handle accordingly (refund, manual review, etc.).
Transaction events:
transaction.received- payment detected on-chain but unconfirmed. Optionally notify the user that payment was detected.transaction.confirmed- payment confirmed on the blockchain.
Webhook security:
- Verify the HMAC-SHA256 signature in the
x-coincircuit-signatureheader using your webhook secret - Use the
x-coincircuit-delivery-idheader for idempotency (store processed delivery IDs and skip duplicates)
4. Track payment state
Store a record linking the CoinCircuit session to your bot's user:
telegramUserIdsessionReference- the CoinCircuit payment session referencestatus("pending","completed","expired")- Any use-case-specific fields (subscription expiry, product ID, etc.)
This lets you look up payment status when a user asks, and lets your webhook handler find the right user to notify.
5. Recurring payments (if applicable)
For subscription-based flows, create a new payment session each billing cycle:
- Before expiry: Send the user a renewal payment link
- On expiry: If not renewed, revoke access or downgrade
- On renewal payment: Update the subscription period
Store the subscriptionPeriodEnd in session metadata so your webhook handler knows the new expiry.
Constraints
- Session
amountis a string in fiat, not a number (e.g."9.99") - Store the
telegramUserIdin both the sessionmetadataandcustomer.telegramIdfor reconciliation - Always verify webhook signatures before taking action
- Only act on
payment.completed, not on partial or pending events successUrlandcancelUrlmust be HTTPS- Supported currencies: NGN, USD. Supported assets: BTC, ETH, USDT, USDC, SOL, BNB, TRX. Supported chains: bitcoin, ethereum, solana, bsc, tron, base, arbitrum.