Install · Quick Start · How It Works · docs.rs
What is ferobot?
ferobot is a Telegram Bot API library for Rust. It covers all methods and types from the official API out of the box, and keeps them in sync automatically.
When Telegram ships a new Bot API version, CI picks up the spec change, regenerates the types and methods, and opens a PR. You get the update without touching anything.
The library is built around Tokio. Every bot method is async, every update runs in its own task, and the dispatcher handles routing, concurrency, and panic recovery out of the box.
Installation
Add this to your Cargo.toml:
[]
= "0.2"
= { = "1", = ["full"] }
Optional features you can enable:
| Feature | What it adds |
|---|---|
webhook |
Built-in Axum webhook server |
per-chat |
Sequential update processing per chat ID |
redis-storage |
Redis-backed conversation state |
Quick Start
Get your token from @BotFather, then:
use ;
use Context;
async
async
How It Works
Calling methods
Every bot method takes required arguments directly. Optional parameters are passed through a params struct, or you can skip them entirely with None:
// send a plain message
bot.send_message.await?;
// with optional params chained via builder
bot.send_message
.html
.silent
.reply_to
.await?;
Shortcuts like .html(), .markdown(), .silent(), and .reply_to(id) cover the most common options. For anything else, use the params struct directly:
use SendMessageParams;
let params = new
.parse_mode
.disable_notification;
bot.send_message.await?;
Dispatcher and handlers
The dispatcher routes incoming updates to the first matching handler. Handlers are plain async functions:
dp.add_handler;
dp.add_handler;
dp.add_handler;
Filters compose with .and(), .or(), .not():
// text that is not a command
new
Conversations
For multi-step flows (registration, forms, wizards), use ConversationHandler. It manages state per user and routes each message to the right step:
let conv = new;
State is stored in memory by default. Add the redis-storage feature for persistence across restarts.
ChatId and InputFile
ChatId accepts integers, negative group IDs, and @username strings interchangeably:
bot.send_message.await?;
bot.send_message.await?;
bot.send_message.await?;
InputFile accepts a file ID, a URL, or raw bytes at the same call site:
bot.send_photo.await?; // file_id
bot.send_photo.await?; // URL
bot.send_photo.await?; // bytes
Raw API
If Telegram ships a new method and you can't wait for the next ferobot release, bot.raw() lets you call any method by name with arbitrary params and get back a JSON value.
// call any method by name
let result: Value = bot
.raw
.param
.param
.call
.await?;
File uploads work too:
bot.raw
.param
.file
.
.await?;
For fire-and-forget calls where you don't care about the response:
bot.raw
.param
.param
.send
.await?;
You can also deserialize into your own struct instead of serde_json::Value:
let user: MyUser = bot.raw.call.await?;
In practice you rarely need this since CI keeps ferobot in sync within hours of a Telegram release. But it's a useful escape hatch when you're in a hurry or testing something new.
Always Up to Date
ferobot's types and methods are generated from tgapis/x, a machine-readable mirror of the official Telegram Bot API spec. A GitHub Actions workflow watches the spec repo and triggers regeneration whenever the API changes. The generated files (gen_types.rs, gen_methods.rs, fluent.rs) are never edited by hand.
Contributing
One concern per PR. For bugs and features, open a GitHub issue. For security issues, email ankitchaubey.dev@gmail.com.
License
MIT - Copyright (c) 2026 Ankit Chaubey
Built by Ankit Chaubey · Telegram · docs.rs · crates.io
If ferobot saved you time, a star on GitHub means a lot.