Integrations
Telegram Mini App
The Mini App at /telegram is a compact view of an existing FurlPay account inside Telegram. It adds a way to sign in from Telegram. It does not create a second account, a second session system or a separate balance.
Read-only for money
transfers: false. It shows balances and activity from the same account the web app uses; it cannot send a payment. Cards appear only if card issuing is enabled on the deployment, which it currently is not.Screens
Home, cards, pay, activity, profile, wallet and travel, each at /telegram/<screen>. A launch link may carry a start parameter naming one of these screens. The start parameter is a navigation hint only; it never carries an account, a token or a payment.
How sign-in works
- Telegram passes the Mini App a signed launch string. The server verifies it with the bot token (HMAC-SHA256), rejects duplicate or malformed fields, rejects bots, and requires the launch to be recent (default 300 seconds, configurable from 30 to 600).
- If the Telegram user is not linked to a FurlPay account, the response is
link_requiredand no session is created. - If it is linked, the server issues the normal FurlPay session cookie. A signed launch is a one-use credential: it is recorded when used, including when the browser already holds a session, and a second attempt to create a session from it is refused.
- Inside Telegram's embedded browser the session cookie is issued with attributes suited to an embedded context. Remembering that context does not grant authentication.
- Locked or deleted accounts are refused. If a different FurlPay account is already signed in, the response is
409and the user must sign out first.
Linking an account
Linking proves the person controls both identities. The user must be signed in to FurlPay and must have completed a fresh step-up (passkey, or email or phone code) within the last five minutes; guest sessions cannot link. A Telegram account can be linked to one FurlPay account. Neither side can be claimed twice, even by concurrent requests.
The signed-in account can remove its own link. Unlinking needs the same fresh authentication, so a stolen session cannot quietly detach the owner's sign-in method. Sessions already issued are not revoked by unlinking; signing out of FurlPay does that.
API
| Method | Path | Description |
|---|---|---|
| POST | /api/auth/telegram | Verify a launch and sign in; returns active or link_required |
| POST | /api/miniapp/telegram-link | Link the verified Telegram user to the signed-in account (fresh authentication required) |
| DELETE | /api/miniapp/telegram-link | Remove the signed-in account's own link (fresh authentication required) |
| GET | /api/miniapp/account | Narrow account view: profile name, verification state, balances, last 200 activity rows, capabilities |
| POST | /api/telegram/webhook | Bot updates from Telegram, authenticated by the secret-token header |
The account view is a whitelist. It never returns a full profile, card numbers, the security object, a placeholder deposit address or an invented blockchain receipt.
Setup
| Parameter | Type | Description |
|---|---|---|
| TELEGRAM_BOT_TOKENrequired | secret | Server-only. Used to verify launches. |
| TELEGRAM_WEBHOOK_SECRETrequired | secret | Must match the secret token registered with Telegram's setWebhook. Requests without it get 401. |
| TELEGRAM_AUTH_MAX_AGE_SECONDSoptional | number | Launch freshness window, 30 to 600. Default 300. |
| NEXT_PUBLIC_TELEGRAM_BOT_USERNAMEoptional | public | Bot username without the @, as confirmed by BotFather. Leave unset until the Mini App is configured; browser preview still works. |
| NEXT_PUBLIC_TELEGRAM_APP_SHORT_NAMEoptional | public | Short name for a named Mini App. Leave blank for the bot's main Mini App. |
- Migration
0050_telegram_account_linksstores identity links only. - It reuses
FURLPAY_SESSION_SECRET, the Supabase credentials and the Upstash Redis credentials. There is no second auth store. - In BotFather, set the Mini App URL to
https://<your-domain>/telegram.npm run telegram:setupis an operator command that configures the bot;TELEGRAM_MINI_APP_URLis read by that command only, not by the app.
Troubleshooting
| Parameter | Type | Description |
|---|---|---|
| 503 temporarily_unavailablerequired | sign-in | The rate limiter could not reach its key-value store and refused the request. Sign-in is rate limited before anything else runs, and in production it fails closed without that store. |
| 503 Telegram sign-in is temporarily unavailablerequired | sign-in | The bot token is missing, the database is not configured, or the production key-value store is not available. |
| 401 Invalid or expired Telegram sessionrequired | sign-in | The launch string failed verification or is older than the freshness window. Close and reopen the Mini App. |
| 401 This launch was already usedrequired | sign-in | The launch string has already created a session. Close and reopen the Mini App. |
| 403 Invalid request originrequired | sign-in | The request did not come from the deployment's own origin. |
| 409required | sign-in / link | A different FurlPay account is signed in, or one of the two accounts is already linked. |
| 401 on the webhookrequired | bot | The secret-token header does not match TELEGRAM_WEBHOOK_SECRET. |
