FPT Chat Bot API
TypeScript SDK for building FChat bots: handle webhooks, send messages/media/files, upload to storage, and manage inline keyboards.
webHook) is experimental and not recommended for production.onTextEvent, onMedia, onFile, onCallbackQuery, onUpdateMediaFile, onUpdateInlineKeyboard, etc.axios config and timeouts.Authorization header).getUpdates by groupId.``bash`
npm install fchat-bot-apior
yarn add fchat-bot-api
`ts
import express from "express";
import { FChatBot } from "fchat-bot-api";
const bot = new FChatBot(process.env.FCHAT_TOKEN ?? "", {
baseURL: FChatBot.prodBaseUrl(), // or FChatBot.uatBaseUrl()
});
// Typed listeners
bot.onTextEvent((update) => {
console.log("Text:", update.message.text);
});
bot.onMedia((update, metadata) => {
console.log("Media count:", metadata?.medias?.length);
});
bot.onFile((update, metadata) => {
console.log("File name:", metadata?.files?.[0]?.name);
});
bot.onCallbackQuery((payload) => {
console.log("Callback query data:", payload.data);
});
// Regex listener (legacy style)
bot.onText(/hello/i, async (update) => {
await bot.sendMessage(update.groupId, "Hi there!");
});
const app = express();
app.use(express.json());
app.post("/webhook", (req, res) => {
bot.processUpdate(req.body);
res.sendStatus(200);
});
const port = Number(process.env.PORT ?? 3000);
app.listen(port, () => {
console.log(Webhook listening on :${port});`
});
> Note: the webHook option (built-in server) is experimental; prefer Express/your own web server to receive webhooks.
`ts
// Text + inline keyboard
await bot.sendMessage("group-id", "Choose an option", {
replyMarkup: {
inlineKeyboard: [
[{ text: "Ping", callbackData: "ping" }],
[{ text: "Visit site", callbackData: { url: "https://chat.fpt.com" } }],
],
},
});
// Typing indicator
await bot.sendTyping({ groupId: "group-id", typingType: "TEXT" });
`
`ts
// Photo: upload and send in one call
await bot.sendPhoto("group-id", "/path/to/photo.jpg", {
captionName: "Screenshot",
width: 800,
height: 600,
});
// Video: requires thumbnail + metadata
await bot.sendVideo("group-id", "/path/to/video.mp4", {
thumbnail: "/path/to/thumb.jpg",
width: 1280,
height: 720,
duration: 12,
});
// Generic file (pdf/zip/...) with mentions
await bot.sendFile("group-id", "/path/to/report.pdf", {
metadata: { mentions: [{ target: "user@example.com", offset: 0, length: 0 }] },
});
`
`ts
// Upload to storage and get media id
const upload = await bot.uploadStorageFile({
file: { path: "/path/to/image.png" },
type: "IMAGE",
captionName: "Logo",
});
// Send by media id (no re-upload)
await bot.sendMedia("group-id", upload?.metadata?.medias?.[0]?.id);
`
`ts`
await bot.editMessageReplyMarkup({
groupId: "group-id",
messageId: 123,
text: "Updated buttons",
replyMarkup: { inlineKeyboard: [[{ text: "New CTA", callbackData: "new" }]] },
});
Not recommended for production; prefer Express/your own server. For internal testing:
`ts
const bot = new FChatBot(process.env.FCHAT_TOKEN ?? "", {
baseURL: FChatBot.uatBaseUrl(),
webHook: {
host: "0.0.0.0",
port: 8443,
path: "/webhook",
https: { key: fs.readFileSync("key.pem"), cert: fs.readFileSync("cert.pem") },
autoOpen: true,
secretToken: "verify-this-in-your-proxy",
},
});
bot.onWebhookError(console.error);
`
| API | Description |
| --- | --- |
| setWebhook({ url }), deleteWebHook() | Configure or remove webhook (header-auth). |getUpdates({ groupId, page?, limit? })
| | Fetch updates by group (polling). |getMe()
| | Bot info. |setAvatar({ avatarUrl })
| | Update bot avatar. |listStorageFiles({ page?, limit? })
| , getStorageInfo() | List storage files and usage info. |sendMessage
| , sendMedia, sendPhoto, sendVideo, sendFile, sendTyping, editMessageReplyMarkup | Send content/typing; edit inline keyboards. |
: missing required fields or invalid data (e.g., missing groupId, unsupported MIME).
- FChatError: HTTP errors from the API (includes status, code, body).
- ParseError, FatalError`: lower-level issues (network/JSON).