Feishu Bitable Integration in Practice
When teams use Feishu alongside internal systems, Bitable often becomes a lightweight layer for data entry, process coordination, and day-to-day collaboration.
If you want to sync that data into your own system, the requirements usually fall into three categories:
- Sync newly created records into your system automatically
- Detect table changes and notify your system as quickly as possible
- Write data back to Bitable from your own application
This article summarizes a practical integration approach based on real project experience.
In practice, this kind of integration helps reduce manual handoffs, improve data reliability, and make internal workflows easier to automate.
1. The preferred approach: trigger a webhook with automation
If your system can expose a public endpoint, the most straightforward approach is to use Feishu Bitable Automation to call your webhook whenever a new record is created.
Compared with polling the Bitable API on a schedule, this approach is usually better for low-frequency but time-sensitive sync scenarios because:
- It avoids continuous polling and reduces resource usage
- The trigger flow is easier to understand and troubleshoot
- Data sync is closer to real time
Basic flow
- Create a webhook endpoint in your system
- Configure an automation rule in Feishu Bitable
- When a user creates a new record, Feishu calls the webhook automatically
- Your system receives the payload and completes the required business logic
This pattern works well for cases like lead capture, ticket creation, internal registration flows, and similar record-driven processes.
2. An alternative when you cannot expose a public endpoint
Not every system is able or willing to expose a public webhook URL.
If your application runs in an internal network, a testing environment, or another restricted setup, a practical fallback is:
Use Bitable Automation to send change notifications to a Feishu group chat, then let your system listen to those messages through a long-lived connection.
The idea is simple:
- Bitable emits the change notification
- A Feishu group acts as the delivery channel
- Your system listens for messages through a WebSocket connection
This lets you receive change notifications without making your service publicly accessible.
3. Recommended integration architecture
In practice, we usually recommend the following flow:
- Create a Feishu custom app
- Enable bot capability and message-reading permissions
- Turn on event subscriptions through a long connection
- Configure Bitable Automation to send change notifications into a group chat
- Let your system listen to those messages and then call Bitable APIs to read or update data
In some scenarios, Bitable-related events are not the best standalone trigger source.
Because of that, the combination of automation, group-message notifications, and system-side API operations is often easier to control and more reliable in real-world implementations.
4. Feishu app setup essentials
1. Create a custom app
After creating an app in the Feishu Open Platform, you should at least:
- Enable the
botcapability - Add message-reading permissions
- Enable
long connectionas the event subscription method
If your system also needs to read from or write to Bitable, you will need the relevant Bitable permissions as well.
2. Common permissions to review
For listening to group messages, you will typically need:
im:messageim:message.group_msg
For reading and writing Bitable data, you will typically need:
bitable:app
Permission names and scopes may evolve over time, so it is worth double-checking the current configuration in the Feishu Open Platform before going live.
3. Save your app credentials
Make sure you keep the following values available for your server-side integration:
App IDApp Secret
Your backend can then use them to obtain a tenant_access_token before calling Feishu APIs.
5. Automation setup notes for Bitable
Inside Bitable, you can configure automation rules with triggers such as “record created” or “record updated”, and set the action to send a Feishu group message.
One detail is easy to miss:
It is generally safer for the notification to originate from a user-side action rather than a bot-generated message alone.
Feishu’s event model is designed to prevent message loops.
If the notification is produced entirely by a bot, your system may not receive the callback in the way you expect.
A more reliable pattern is:
- Let Bitable Automation send a message into a target group
- Listen for that group message in your system
- Trigger your own business logic or Bitable API calls after receiving it
6. Receiving events through a long connection
Feishu supports a WebSocket-based long connection for event delivery.
Once the subscription is configured, Feishu can push events directly to your service over that connection.
This works especially well when:
- Your service is not exposed to the public internet
- You want to avoid additional webhook infrastructure
- You need to test or validate the workflow in a local or internal environment
Here is a simplified example:
import * as Lark from "@larksuiteoapi/node-sdk";
const baseConfig = {
appId: "xxx",
appSecret: "xxx",
};
const wsClient = new Lark.WSClient({
...baseConfig,
loggerLevel: Lark.LoggerLevel.debug,
});
wsClient.start({
eventDispatcher: new Lark.EventDispatcher({}).register({
"im.message.receive_v1": async (data) => {
console.log(data);
// Parse the message content here
// Then trigger your business logic or Bitable API operations
},
}),
});
If your goal is simply to detect that a record was added or changed, this message-listening approach is often enough.
7. Reading and writing Bitable data with the SDK
Once your system receives a notification, the next step is usually to query record details from Feishu or write the processing result back into Bitable.
Common parameters
When updating a record, you will usually need:
app_token: the application-level identifier for the Bitabletable_id: the table IDrecord_id: the record IDfields: the field values you want to update
In most cases:
app_tokencan be obtained from the Bitable URL or object informationrecord_idcan be captured from automation callbacks or fetched in a follow-up query
Example: updating a record
The following example shows a simple wrapper around the basic API flow:
import axios from "axios";
import keys from "../../configBridge";
interface FeishuConfig {
app_id: string;
app_secret: string;
}
interface TokenInfo {
token: string;
expiresAt: number;
}
export class Feishu {
private config: FeishuConfig;
private tenantTokenInfo: TokenInfo | null = null;
constructor() {
this.config = {
app_id: keys.feishu.FEISHU_APP_ID || "",
app_secret: keys.feishu.FEISHU_APP_SECRET || "",
};
}
private isTokenExpired(tokenInfo: TokenInfo | null): boolean {
if (!tokenInfo) return true;
return Date.now() >= tokenInfo.expiresAt;
}
async getTenantAccessToken() {
if (!this.isTokenExpired(this.tenantTokenInfo)) {
return this.tenantTokenInfo!.token;
}
const response = await axios.post(
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
{
app_id: this.config.app_id,
app_secret: this.config.app_secret,
}
);
const data = response.data;
if (data.code !== 0 || !data.tenant_access_token) {
throw new Error(`Failed to get tenant_access_token: ${data.msg}`);
}
const expiresIn = data.expire;
this.tenantTokenInfo = {
token: data.tenant_access_token,
expiresAt: Date.now() + expiresIn * 1000 - 60_000,
};
return this.tenantTokenInfo.token;
}
async updateRecord(params: {
appToken: string;
tableId: string;
recordId: string;
fields: Record<string, any>;
}) {
const token = await this.getTenantAccessToken();
const url = `https://open.feishu.cn/open-apis/bitable/v1/apps/${params.appToken}/tables/${params.tableId}/records/${params.recordId}`;
const response = await axios.put(
url,
{ fields: params.fields },
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (response.data.code !== 0) {
throw new Error(`Failed to update record: ${response.data.msg}`);
}
return response.data;
}
}
8. Practical recommendations
If your only goal is to sync newly created records into your system, start with:
Automation + Webhook
If your system cannot expose a public endpoint for now, consider:
Automation + Group Message Notification + Long Connection Listener
If you also need to write data back, update statuses, or enrich records, add:
Feishu SDK / API operations for Bitable
This separation works well because the notification path and the data-operation path stay independent, making the integration easier to debug and extend later.
Conclusion
Feishu Bitable is more than a collaboration tool. In many projects, it can serve as a lightweight bridge between operational workflows and internal business systems.
The right integration approach depends less on whether the API can be called, and more on questions like:
- Can your system expose a public endpoint?
- Do you need near-real-time notifications?
- Do you need to write processed results back into Bitable?
If you combine webhooks, long-connection events, and API-based data operations in a way that matches your deployment model, Bitable can fit into your system architecture quite naturally.