Build the bot code only. The platform supplies the saved Telegram token and username automatically.
This is the complete user-bot contract for this platform. The intended custom root entry file is exactly bot.php. Users save the BotFather token and bot username on the Create Bot page. Create verifies the token immediately, synchronizes Telegram's real username, creates a safe default bot.php, and currently attempts one automatic Start. At Start/Restart, the runtime injects BOT_TOKEN and BOT_USERNAME before loading user code. Save/Edit/Import change private files only, so changed code must be activated with Restart when running or Start/Deploy when stopped.
The current Create Bot flow attempts an automatic Start once for the generated default bot. After that, Save, Edit, direct file import and ZIP import only change private project files; they do not refresh a running webhook runtime. After changing code, use Save → Restart when the bot is running, or Start/Deploy when it is stopped.
Runtime truth — this overrides framework guesses
Any AI or developer must follow these exact rules.
| Item | Exact requirement |
|---|---|
| Runtime | Plain PHP request lifecycle for Telegram webhooks |
| Custom entry file | Exact lowercase root bot.php. Create makes a default file; Start/Restart currently repairs a missing root file with the safe default, so custom deliveries must include their intended root bot.php. |
| Telegram input | JSON read from php://input |
| Credentials | BOT_TOKEN and BOT_USERNAME are predefined by the platform runtime |
| User source | Must not hard-code or redefine the BotFather token or bot username |
| Activation | Create currently attempts one automatic Start. Later, Start or Deploy activates a stopped bot; saving code alone does not refresh runtime. |
| After edit | Running bot: Save, then Restart. Stopped bot: Save, then Start/Deploy. |
| Polling | Not supported; no infinite loop or persistent worker |
| Normal bot storage | No SQL required; local JSON is allowed when state is needed |
| User framework | No Laravel project, no Artisan, no migrations, no user .env |
| Preferred PHP | PHP 8.1+ compatible plain PHP |
Automatic runtime-managed credentials
This is the most important rule for generated code.
The website already owns the values entered on Create Bot. During Start/Restart, the saved token is decrypted server-side, verified against Telegram, and provisioned to the private runtime. User project files and exported ZIPs do not need the token or username.
<?php
declare(strict_types=1);
if (!defined('BOT_TOKEN') || !defined('BOT_USERNAME')) {
http_response_code(503);
exit('Runtime credentials unavailable');
}
// Use them directly. Do not define their values yourself.
$url = 'https://api.telegram.org/bot'.BOT_TOKEN.'/getMe';
$currentUsername = BOT_USERNAME;Use BOT_TOKEN and BOT_USERNAME as already-defined constants.
Do not write const BOT_TOKEN = '123...', do not add token placeholders, and do not put username values in source.
The platform currently manages the Telegram bot token and bot username. If a bot feature needs a private admin Telegram user ID, keep only that bot-specific value in PHP, for example const ADMIN_ID = 123456789;, unless a future dashboard field is provided for it.
Exact file names and project shapes
One file is preferred. A few helper files are allowed.
bot.php
bot.php + admin.php
bot.php, helpers, optional JSON data
index.php, webhook.php, nested-only mybot/bot.php
bot.phpbot.php
admin.php
functions.php
data/
users.json
settings.jsonThe intended custom entry is exact root bot.php. A ZIP that extracts only to my-bot/bot.php will not run that nested file as the entry. Because Start/Restart currently repairs a missing root file with the safe default bot, a wrong ZIP shape can appear to “start” while your intended code is not running.
Exactly what Start, Restart, Deploy and Stop do
Code storage and runtime activation are separate operations.
| Control | What it does | When to use |
|---|---|---|
| Create Bot | Verifies the token with Telegram, syncs the authoritative username, creates a safe default root bot.php, saves the bot, then currently attempts an automatic Start. | Initial bot creation |
| Save / Edit / Import | Changes private user files only. It does not refresh an already active runtime. | Whenever adding or editing files |
| Start | Ensures root bot.php exists (currently generating the safe default if missing), security-scans all PHP, verifies saved token with Telegram, resolves/syncs actual username, creates private runtime credentials, injects constants, enables the protected endpoint and sets webhook. | Activate a stopped bot |
| Restart | Removes old webhook/runtime, removes old private runtime credentials, then performs a fresh Start from current files and saved dashboard credentials. | After editing a running bot |
| Deploy | Runs the same fresh activation path as Start for the current project. | When using deployment wording/workflow |
| Stop | Deletes Telegram webhook, removes public runtime entry and removes private runtime credential files. | Pause the bot cleanly |
| Force Stop | Stops runtime and requests pending Telegram updates be dropped. | Emergency shutdown or stale update cleanup |
Complete one-file PHP webhook bot
This sample uses automatic runtime credentials and replies to /start.
<?php
declare(strict_types=1);
// Injected automatically at Start/Restart by the platform.
// Never hard-code or redefine the token or username.
if (!defined('BOT_TOKEN') || !defined('BOT_USERNAME')) {
http_response_code(503);
exit('Runtime credentials unavailable');
}
// Optional bot-specific value only when your feature needs an admin.
const ADMIN_ID = 123456789;
function telegramApi(string $method, array $data = []): array
{
$url = 'https://api.telegram.org/bot'.BOT_TOKEN.'/'.$method;
$raw = false;
$error = '';
if (function_exists('curl_init')) {
$ch = curl_init($url);
if ($ch === false) {
return ['ok' => false, 'description' => 'Unable to initialize cURL.'];
}
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ['Accept: application/json'],
]);
$raw = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
} else {
// Shared-hosting fallback when the PHP cURL extension is not installed.
$payload = http_build_query($data, '', '&', PHP_QUERY_RFC3986);
$context = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\nAccept: application/json\r\n",
'content' => $payload,
'timeout' => 20,
'ignore_errors' => true,
],
]);
$raw = @file_get_contents($url, false, $context);
if (!is_string($raw)) {
$error = 'HTTP request failed. Enable php-curl or allow_url_fopen.';
}
}
if (!is_string($raw)) {
return ['ok' => false, 'description' => $error !== '' ? $error : 'Telegram request failed.'];
}
$decoded = json_decode($raw, true);
return is_array($decoded)
? $decoded
: ['ok' => false, 'description' => 'Invalid Telegram response.'];
}
$rawInput = file_get_contents('php://input');
$update = json_decode(is_string($rawInput) && $rawInput !== '' ? $rawInput : '{}', true);
if (!is_array($update)) {
http_response_code(200);
echo 'OK';
exit;
}
$message = $update['message'] ?? null;
if (is_array($message) && isset($message['chat']['id'])) {
$chatId = (string) $message['chat']['id'];
$text = trim((string) ($message['text'] ?? ''));
$commandPattern = '~^/start(?:@'.preg_quote(BOT_USERNAME, '~').')?(?:\\s|$)~i';
if (preg_match($commandPattern, $text) === 1) {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Hello! @'.BOT_USERNAME.' is running ✅',
]);
}
}
http_response_code(200);
echo 'OK';It has exact root entry semantics, reads webhook JSON, uses the runtime-provided token/username, has no SQL/Laravel/.env requirement, has no polling loop, and responds safely with HTTP 200.
PHP + HTML in one page
A single bot.php may handle Telegram POST requests and show an HTML status page for browser GET requests.
<?php
declare(strict_types=1);
if (!defined('BOT_TOKEN') || !defined('BOT_USERNAME')) {
http_response_code(503);
exit('Runtime credentials unavailable');
}
if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
$update = json_decode(file_get_contents('php://input') ?: '{}', true);
// Handle Telegram update here using BOT_TOKEN and BOT_USERNAME.
http_response_code(200);
echo 'OK';
exit;
}
?>
<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Bot Status</title></head>
<body>
<h1>@<?= htmlspecialchars(BOT_USERNAME, ENT_QUOTES, 'UTF-8') ?></h1>
<p>Runtime is online.</p>
</body>
</html>An index.html file cannot receive and process Telegram webhook JSON. Keep the exact root entry bot.php; HTML may be rendered from that PHP file.
When requirements are described in Laravel terms
Convert the behavior to this runtime; do not output a Laravel user project.
| Laravel-style request | Runtime-compatible conversion |
|---|---|
| Route / webhook route | Request branching inside root bot.php |
| Controller | Normal PHP functions or a small included helper file |
| Service class | Plain PHP helper function/class when genuinely useful |
.env bot token | Do not create it; use platform-provided BOT_TOKEN |
| Configured bot username | Do not duplicate it; use platform-provided BOT_USERNAME |
| Migration / model | Usually unnecessary; use locked JSON only when local state is needed |
| Queue worker | Webhook request handling; no persistent process |
| Artisan command | Not part of user-bot delivery |
I may describe features using Laravel terms, but do not output a Laravel project for this bot host. Convert the requested behavior to the platform contract: exact root bot.php, plain PHP webhook input from php://input, no Artisan, no migrations, no user .env, no user Laravel routes/controllers, no persistent worker. BOT_TOKEN and BOT_USERNAME are already defined automatically by the platform at Start/Restart from the values saved on Create Bot. Use those constants directly. Never ask me to paste the token or bot username into PHP source.Master AI / ChatGPT / developer prompt
Give the docs URL plus this contract. Replace only the feature requirement at the bottom.
Read and follow these platform documents exactly:
Human docs: https://botbhai.top/docs/bot-development
AI-readable Markdown contract: https://botbhai.top/docs/bot-development/ai.md
Build a complete Telegram bot for this custom bot-hosting runtime.
MANDATORY RUNTIME CONTRACT
1. Output plain PHP compatible with PHP 8.1+.
2. For every intended custom delivery, provide the exact lowercase root entry file bot.php. Do not rely on the runtime's missing-file default repair.
3. Prefer one complete bot.php file. Use only a few helper files when genuinely needed.
4. Telegram updates arrive as JSON through php://input.
5. Webhook mode only. No long polling, infinite loop, daemon or persistent worker.
6. Do not output a Laravel project, Artisan command, migration, Composer setup, Node.js worker or Python worker.
7. Do not require SQL for a normal bot. If small persistent state is needed, use local JSON with safe file locking and atomic writes.
CRITICAL MANAGED-CREDENTIAL RULE
8. The user already saves the BotFather token and bot username on the website Create Bot page. Create verifies Telegram identity, creates a default bot.php, and currently attempts auto-start once.
9. At Start/Restart the platform verifies Telegram identity and automatically defines BOT_TOKEN and BOT_USERNAME before bot.php runs.
10. Use BOT_TOKEN and BOT_USERNAME directly as predefined constants.
11. NEVER hard-code, redefine, request, print, log or expose the bot token or bot username value in PHP source.
12. Do not create BOT_TOKEN/BOT_USERNAME placeholders.
13. Do not create a bot .env file for these values.
14. Add a safe runtime guard when appropriate:
if (!defined('BOT_TOKEN') || !defined('BOT_USERNAME')) { http_response_code(503); exit('Runtime credentials unavailable'); }
15. ADMIN_ID is not automatically managed by this contract. If the requested features need a private admin Telegram user ID, use a clearly marked numeric ADMIN_ID placeholder only.
TELEGRAM/API RULES
16. Use BOT_TOKEN when building Telegram Bot API URLs.
17. Use BOT_USERNAME without assuming an @ prefix; the platform provides the normalized username.
18. Handle /command and /command@BotUsername safely.
19. Use cURL with connection and total timeouts.
20. Validate Telegram update shapes before reading nested keys.
21. Return HTTP 200 safely after webhook handling.
22. Escape HTML when using parse_mode=HTML.
23. Validate callback_data with an allowlist or strict pattern.
24. Verify ADMIN_ID before every admin-only action.
SECURITY RULES
25. No exec, system, shell_exec, passthru, proc_open, popen, backticks or shell/process execution.
26. No eval, assert-as-code, dynamic function invocation tricks, Reflection-based invocation or untrusted PHP execution.
27. No remote PHP include/require.
28. Prevent path traversal and sanitize filenames.
29. Lock JSON writes with flock/LOCK_EX and use atomic replacement when data integrity matters.
30. Never expose secrets in HTML, JavaScript, logs, callback data or API output.
31. Use bounded input sizes and HTTP timeouts.
OUTPUT RULES
32. First show the exact file tree.
33. Then provide every required file in full, one code block per file.
34. No pseudo-code, TODOs, omitted sections or “continue yourself”.
35. Do not include SQL, .env, Laravel scaffolding or token/username placeholders.
36. End with exact platform steps:
Create Bot with token + username (the current app verifies identity, creates default bot.php and attempts auto-start) → save/import the intended root bot.php → if running Restart, if stopped Start/Deploy → test /start → after later running-code edits Save → Restart.
37. Explicitly state that Save/Edit/Import do not refresh a running runtime; activation or restart is required for changed code.
MY BOT REQUIREMENT
[Write the complete bot features here]Best result: give the AI-readable Markdown URL https://botbhai.top/docs/bot-development/ai.md plus your features. You may also give the human page https://botbhai.top/docs/bot-development. The Markdown route removes page-navigation noise and states the actual Create/Start/Restart lifecycle explicitly.
PHP and ZIP import/export rules
Project files are separate from dashboard-managed Telegram credentials.
For your intended custom code to run, the imported project should result in root bot.php. If only a nested folder/bot.php exists, Start/Restart may generate the safe default root bot instead, so the webhook can run the wrong code. Never put BotFather tokens into ZIP files; the platform injects saved dashboard credentials at runtime.
Security requirements for generated bot code
Runtime-managed credentials reduce accidental token duplication, but safe code is still mandatory.
Use it only for Telegram API requests. Never print, log, serialize or send it to clients.
Compare numeric sender ID before every private/admin action.
Validate commands, callbacks, URLs, IDs and filenames.
No exec/system/shell_exec/passthru/proc_open/popen or equivalent tricks.
No eval, untrusted include, generated PHP execution or dynamic callable bypass tricks.
Use connection and total timeouts for Telegram and external APIs.
Use __DIR__, normalize/allowlist names and prevent traversal.
Use flock()/LOCK_EX and atomic replacement when state matters.
If Start/Restart rejects risky PHP, redesign the feature with normal webhook-safe code. Do not obfuscate, dynamically invoke, reflect, encode or otherwise bypass blocked execution primitives.
Debugging in the correct order
Separate file-storage problems from activation, credential verification, webhook and bot-logic problems.
| Problem | Likely cause | First action |
|---|---|---|
| Saved/imported code but bot does nothing | Stopped bot was not activated, or imported file is not the root entry | If stopped press Start/Deploy; confirm intended exact root bot.php |
| Edited code but old behavior remains | Runtime was not refreshed | Running bot: Save, then press Restart |
| Bot starts but only default /start behavior runs | Root bot.php was missing; nested/wrong ZIP shape caused the runtime to repair it with the safe default | Move intended code to exact root bot.php, save/import, then Restart |
| Start rejects saved token | Invalid/revoked BotFather token | Recreate/correct bot credentials in dashboard |
| Username shown changes after Start | Telegram token belongs to a different/current username | This is expected; Start syncs Telegram's verified username |
| Runtime credentials unavailable | Opening bot.php outside platform Start/Restart runtime | Use platform Start; do not browse/execute project source directly |
| Start shows security error | Blocked high-risk PHP primitive | Replace with normal webhook-safe PHP |
| Starts but does not reply | Logic, cURL, API request or update-shape bug | Test the minimal example and inspect Logs |
| ZIP import fails | Corrupt/encrypted/unsafe/oversized archive | Create a normal unencrypted relative-path ZIP |
| Save fails | Invalid filename, request limit, disk/permission issue | Use a relative name such as bot.php and read the error |
- 1Confirm root
bot.phpExact lowercase filename, no extra outer ZIP folder.
- 2Confirm dashboard credentials
Create Bot must have a valid BotFather token and username.
- 3Activate the current files
Create may already have auto-started the default bot. After saving/importing intended code: running bot → Restart; stopped bot → Start/Deploy.
- 4Send
/startThen inspect runtime logs and Telegram API behavior.
- 5After every running-code change
Save and press Restart.
Final delivery checklist for any AI or developer
A generated answer is incomplete until every item passes.