Download the PHP package thexerc/laravel-bale without Composer
On this page you can find all versions of the php package thexerc/laravel-bale. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package laravel-bale
laravel-bale
A first-class Laravel package for building Bale messenger bots and Bale Mini Apps. Everything you need in one composer require — bot API client, webhook handling, long polling, command router, Laravel events, payment helpers, file helpers, and a JavaScript SDK for Mini Apps.
Table of Contents
- Requirements
- Installation
- Configuration
- Environment Variables
- Multiple Bots
- Receiving Updates
- Webhook Mode
- Long Polling Mode
- Sending Messages
- Basic Text Message
- Parse Mode (Markdown / HTML)
- Replying to a Message
- Deleting a Message
- Forwarding a Message
- Keyboards
- Inline Keyboard
- Reply Keyboard
- Remove Keyboard
- Sending Media
- Photo
- Document
- Video
- Audio & Voice
- Location
- Contact
- File Helpers
- Command & Message Routing
- Registering Commands
- Class-based Handlers
- Message Pattern Matching
- Callback Query Routing
- Laravel Events
- Payments
- Mini Apps
- Backend: Validating initData
- Frontend: JavaScript Helper
- Multiple Bots
- Artisan Commands
- Objects Reference
- Troubleshooting
Requirements
| Requirement | Version |
|---|---|
| PHP | ≥ 8.1 |
| Laravel | 10 or 11 |
| Guzzle | ≥ 7.0 |
Installation
The package auto-discovers itself via Laravel's package auto-discovery. No manual provider registration is needed.
Publish the config file:
This creates config/bale.php in your application.
Optionally publish the stubs (so you can customise generated handler classes):
Optionally publish the Mini App JS assets to public/vendor/bale/js/:
Configuration
Environment Variables
Add the following to your .env file:
Published Config (config/bale.php)
GitHub Copilot Agent
The package ships a GitHub Copilot agent that gives Copilot precise, domain-specific context about Bale development. It installs:
.github/instructions/laravel-bale.instructions.md— always-loaded context with a skill routing table that tells Copilot exactly which skill to load for each Bale task vs. which Laravel Boost skill to use for general Laravel work..github/skills/bale-*/SKILL.md— five on-demand skill files that are loaded only when relevant.
Setup with Laravel Boost (recommended)
If your project uses Laravel Boost, the agent is registered automatically. Run:
Select GitHub Copilot (VS Code) from the agent list. Boost will write all files to .github/.
Keep the generated files out of source control (they are regenerated by boost:install):
Standalone setup (without Laravel Boost)
This writes the same files without requiring Boost. Commit them to source control so your whole team benefits.
How skill routing works
Copilot loads the instructions file upfront. It contains a routing table that maps every Bale task to the correct skill and every general Laravel task to a Laravel Boost skill:
| Task | Skill loaded |
|---|---|
| Creating a handler, registering commands | /bale-bot-development |
| Building keyboards (inline / reply) | /bale-bot-development |
| Mini App initData validation, JS SDK | /bale-miniapp-development |
| Invoices, pre-checkout, payments | /bale-payments |
| Sending/receiving photos, videos, files | /bale-media-handling |
| Banning, restricting, pinning, chat settings | /bale-chat-administration |
| Writing tests | /pest-testing (Boost) |
| Livewire / Inertia components | /livewire-development (Boost) |
| General Laravel | Laravel Boost guidelines |
Copilot reads this table and loads only the skill relevant to your current task, keeping the context window focused.
Available skills
| Skill | Activates when |
|---|---|
bale-bot-development |
Building handlers, routing updates, keyboards, webhook/polling |
bale-miniapp-development |
Mini App backend validation, JS SDK, web_app_data |
bale-payments |
Invoices, pre-checkout, fulfillment, transactions |
bale-media-handling |
Sending/receiving photos, videos, documents, albums |
bale-chat-administration |
Banning, restricting, promoting, pinning, chat settings |
Pinning Messages
Chat Info & Photo
Member Permissions
Invite Links
Editing Message Media
Replace the photo, video, document, or animation of an already-sent message:
Multiple Bots (named)
Access a specific bot by name anywhere with Bale::bot('support') (see Multiple Bots).
Receiving Updates
Webhook Mode
1. Register the webhook (one-time setup):
This automatically constructs the correct URL from APP_URL + your configured prefix + bot token, e.g. https://your-app.com/bale/webhook/your-bot-token.
The package registers the route for you — no changes to routes/web.php or routes/api.php are needed. The CSRF middleware is not applied to this route.
2. Register your handlers in a service provider or AppServiceProvider::boot():
When Bale sends an update to your webhook URL, the package automatically parses it, fires the appropriate Laravel events, and routes it to your handlers.
Long Polling Mode
If your server is not publicly accessible (e.g. local development), use long polling:
This command runs indefinitely, fetching updates from Bale and dispatching them through the same router and events as webhook mode. It automatically removes any existing webhook before starting.
Options:
Production note: For production, always prefer webhook mode. Use long polling only for local development or environments without a public URL.
Sending Messages
All send methods are available on the Bale facade (default bot) or on a specific BotApi instance returned by Bale::bot('name').
Basic Text Message
Parse Mode
Bale supports Markdown and HTML formatting:
Replying to a Message
Deleting a Message
Forwarding a Message
Editing a Message
Keyboards
Inline Keyboard
Inline keyboards appear directly below the message.
Reply Keyboard
Reply keyboards replace the user's text input area.
Remove Keyboard
Sending Media
All media methods accept the same $options array for additional parameters like caption, reply_markup, reply_to_message_id, etc.
Photo
Document
Video
Audio & Voice
Location
Contact
Animation (GIF)
Media Group (Album)
Send 2–10 photos or videos as an album. You can mix file_id, URLs, and local file paths — the package automatically switches to multipart upload when local files are detected:
Copy Message
Copy a message to another chat without the "Forwarded from" label:
Chat Action (Typing Indicator)
Show a status indicator while your bot is processing:
File Helpers
When a user sends a document, you can retrieve and download it like this:
Bale file size limit: Bots can download files up to 20 MB.
Command & Message Routing
Registering Commands
Register handlers in AppServiceProvider::boot() (or any service provider):
Class-based Handlers
Generate a handler class with the artisan command:
This creates app/Bale/Handlers/StartHandler.php:
Handler classes are resolved out of Laravel's container, so you can type-hint any service in the constructor:
Message Pattern Matching
Match plain text messages using a regex pattern:
Callback Query Routing
Inside a callback handler you can answer the query and optionally edit the original message:
Laravel Events
The package fires these events automatically when an update arrives — whether via webhook or long polling. Register listeners in app/Providers/EventServiceProvider.php:
You can also handle edited messages directly via the router:
All event objects expose the $update (raw Update object) and $bot (BotApi instance for the receiving bot).
Example listener:
Payments
Test token:
WALLET-TEST-1111111111111111
The test token behaves exactly like a real token but does not transfer real money.
Pre-checkout queries also fire a PreCheckoutQueryReceived event, so you can handle them in a listener:
Inquire about a transaction (Bale-specific):
Ask a user to review the bot (Bale-specific):
Mini Apps
Receiving Data from a Mini App
When the Mini App calls Bale.WebApp.sendData(...), the bot receives a message containing a web_app_data field. The package maps this to a WebAppData object:
Backend: Validating initData
Every Mini App request from a user carries initData — a signed string you must validate on the server before trusting the user identity.
The package provides a ready-made endpoint at POST /bale/miniapp/auth and a helper class you can call anywhere.
Using the built-in endpoint:
Validating manually in a controller:
Using the X-Bale-Init-Data header (automatic with BaleApp JS helper):
The JS helper automatically injects X-Bale-Init-Data into every request. In your middleware or controller base class you can validate it once:
Frontend: JavaScript Helper
After publishing assets (php artisan vendor:publish --tag=bale-assets), include the script in your Mini App's HTML:
Or import it as an ES module in your Vite project:
Basic usage:
Full API Reference — BaleApp:
| Method | Description |
|---|---|
new BaleApp({ baseUrl, authEndpoint, headers }) |
Constructor |
await app.ready() |
Initialize — always call first |
await app.authenticate() |
Validate initData with backend, returns user object |
app.user |
Locally parsed user (not server-validated) |
app.initData |
Raw initData string |
await app.get(path, query) |
GET request to your API |
await app.post(path, body) |
POST request |
await app.put(path, body) |
PUT request |
await app.delete(path) |
DELETE request |
app.expand() |
Expand to full screen |
app.close() |
Close Mini App |
app.showMainButton(text, cb) |
Show bottom action button |
app.hideMainButton() |
Hide action button |
app.setMainButtonLoading(bool) |
Show/hide spinner on action button |
app.showBackButton(cb) |
Show native back button |
app.hideBackButton() |
Hide back button |
app.showAlert(msg, cb) |
Native alert dialog |
app.showConfirm(msg, cb) |
Native confirm dialog |
app.sendData(data) |
Send data string/object back to bot |
app.openLink(url, options) |
Open URL in external/in-app browser |
app.openInvoice(url, cb) |
Open a payment invoice; callback receives status |
app.showScanQrPopup(params, cb) |
Show native QR-code scanner |
app.addToHomeScreen() |
Prompt user to add app to home screen |
app.checkHomeScreenStatus(cb) |
Check home-screen shortcut status |
app.requestContact(cb) |
Request user's phone number / contact |
app.askReview() |
Trigger native bot-review prompt |
app.enableClosingConfirmation() |
Show confirm dialog on app close |
app.disableClosingConfirmation() |
Remove closing confirmation |
app.setHeaderColor(color) |
Set title-bar background color |
app.colorScheme |
'light' or 'dark' |
app.themeParams |
Theme color object |
app.onThemeChanged(cb) |
Listen for theme changes |
app.onViewportChanged(cb) |
Listen for viewport changes |
app.onBackButtonPressed(cb) |
Listen for native Back button tap |
app.onSettingsButtonClicked(cb) |
Listen for Settings button tap |
app.onSettingsButtonPressed(cb) |
Alias using the Bale docs canonical event name |
app.onQrTextReceived(cb) |
Listen for successful QR scan; receives { data } |
app.onScanQrPopupClosed(cb) |
Listen for QR popup dismiss without scanning |
app.onInvoiceClosed(cb) |
Listen for invoice screen close; receives { url, status } |
app.onPopupClosed(cb) |
Listen for any native popup dismissal; receives { button_id } |
app.onEvent(eventType, cb) |
Generic passthrough to Bale.WebApp.onEvent() for any event name |
app.offEvent(eventType, cb) |
Remove a previously registered event listener |
app.showSettingsButton(cb) |
Show native Settings (gear) button in header |
app.hideSettingsButton() |
Hide Settings button |
Multiple Bots
Each bot gets its own independent router and event context. Webhooks are set per bot:
Artisan Commands
bale:webhook
Manage the webhook for any bot.
bale:poll
Start long polling (for development).
bale:make-handler
Scaffold a new handler class.
Objects Reference
| Class | Key Properties |
|---|---|
Update |
updateId, message, editedMessage, callbackQuery, preCheckoutQuery, getChatId(), getFrom() |
Message |
messageId, date, chat, from, text, document, photo, photos, video, audio, voice, animation, sticker, contact, location, caption, webAppData, replyToMessage, successfulPayment, getCommand(), getCommandArgs() |
User |
id, isBot, firstName, lastName, username, languageCode, getFullName() |
Chat |
id, type, title, username, firstName, isPrivate(), isGroup(), isChannel() |
CallbackQuery |
id, from, message, data |
PreCheckoutQuery |
id, from, currency, totalAmount, invoicePayload, shippingOptionId, orderInfo |
File |
fileId, fileUniqueId, fileSize, filePath |
Document |
fileId, fileUniqueId, fileName, mimeType, fileSize, thumbnail |
PhotoSize |
fileId, fileUniqueId, width, height, fileSize |
Video |
fileId, fileUniqueId, width, height, duration, thumbnail, mimeType, fileSize |
Audio |
fileId, fileUniqueId, duration, performer, title, mimeType, fileSize |
Voice |
fileId, fileUniqueId, duration, mimeType, fileSize |
Animation |
fileId, fileUniqueId, width, height, duration, thumbnail, mimeType, fileSize |
Sticker |
fileId, fileUniqueId, width, height, isAnimated, thumbnail, emoji, fileSize |
Contact |
phoneNumber, firstName, lastName, userId |
Location |
latitude, longitude |
WebAppData |
data, buttonText, json() |
ChatMember |
user, status, isAdmin(), isMember(), isCreator() |
Invoice |
title, description, currency, totalAmount |
SuccessfulPayment |
currency, totalAmount, invoicePayload, orderInfo, telegramPaymentChargeId, providerPaymentChargeId |
OrderInfo |
name, phoneNumber, email |
WebhookInfo |
url, pendingUpdateCount, lastErrorMessage, isActive() |
Troubleshooting
Webhook returns 401 Unauthorized
Make sure BALE_WEBHOOK_SECRET in your .env matches what you registered with bale:webhook set. If you don't use a secret, leave webhook_secret empty.
Updates not arriving via webhook
- Your
APP_URLmust be HTTPS and publicly reachable. Bale supports ports 80, 88, 443, and 8443. - For local development use a tunnel tool like ngrok and run
php artisan bale:webhook set --url=https://your-tunnel.ngrok.io/bale/webhook/TOKEN. - Run
php artisan bale:webhook infoto see if the webhook URL is correctly registered and checklastErrorMessage.
CSRF errors on the webhook route
The package registers the webhook route outside Laravel's web middleware group, so CSRF verification does not apply. If you have a custom global middleware stack that adds CSRF verification everywhere, exclude the bale/webhook/* path.
Bale.WebApp is not available in the browser console
Your page is being loaded outside the Bale app. The BaleApp JS helper degrades gracefully — API calls still work, but WebApp-specific methods (sendData, showMainButton, etc.) will silently no-op.
initData has expired from MiniAppHelper::validate()
The user opened the Mini App more than miniapp.init_data_ttl seconds ago (default: 1 hour). Ask the user to close and reopen the app. You can raise or disable the TTL in config/bale.php.
Long polling stops after an error
The bale:poll command backs off for 5 seconds after any exception and resumes automatically. Check storage/logs/laravel.log for the error message.
Rate limit errors (429 Too Many Requests)
When Bale rate-limits your bot it returns a ResponseParameters object with retry_after. The package surfaces this on the exception so you can respect it:
License
MIT — see LICENSE.
All versions of laravel-bale with dependencies
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
illuminate/http Version ^10.0|^11.0|^12.0|^13.0
illuminate/console Version ^10.0|^11.0|^12.0|^13.0
guzzlehttp/guzzle Version ^7.0