The Feishu Open Platform provides server-side APIs for messaging, contacts, approval, sheets, Base, and many other product capabilities. This SDK wraps the repeated platform work around API calls, including token management, request signing, encryption/decryption, event dispatching, and typed request/response models.
- Preparations before development
- Calling server-side APIs
- Handle events
- Handle card callbacks
- SDK FAQs
pip install lark-oapiPython 3.8 or later is required.
import lark_oapi as lark
from lark_oapi.api.im.v1 import *
client = lark.Client.builder() \
.app_id("cli_xxx") \
.app_secret("your_app_secret") \
.build()
request = CreateMessageRequest.builder() \
.receive_id_type("chat_id") \
.request_body(CreateMessageRequestBody.builder()
.receive_id("oc_xxx")
.msg_type("text")
.content("{\"text\":\"hello world\"}")
.build()) \
.build()
response = client.im.v1.message.create(request)lark_oapi.register_app creates an app through the OAuth device flow. It
returns a verification URL in on_qr_code; render the URL as a QR code or show
it as a link for the user to open in Feishu/Lark.
import lark_oapi as lark
def on_qr_code(info):
print(info["url"])
result = lark.register_app(
on_qr_code=on_qr_code,
app_preset={
"avatar": [
"https://example.com/a.png",
"https://example.com/b.webp",
],
"name": "{user}'s app",
"desc": "Created by the business platform",
},
)
print(result["client_id"])When creating an app, use addons to incrementally request scopes, event subscriptions,
and callbacks on top of the platform base template. They are pre-filled into the
confirm page shown after the user scans the QR code, and take effect once the user
confirms:
result = lark.register_app(
on_qr_code=on_qr_code,
addons={
"scopes": {
"tenant": ["im:message:send_as_bot"],
"user": ["calendar:calendar:read"],
},
"events": {"items": {"tenant": ["im.message.receive_v1"]}},
"callbacks": {"items": ["card.action.trigger"]},
},
create_only=True,
)
lark.register_app(
on_qr_code=on_qr_code,
app_id="cli_xxx",
addons={"scopes": {"tenant": ["drive:drive.metadata:readonly"]}},
)Notes:
addonsis additive only: items are merged on top of the base template; base permissions can never be removed.- Only the 5 public config types are supported: tenant/user scopes, tenant/user events, and callbacks. Sensitive config such as event request URLs,
security.*, or encrypt keys cannot travel throughaddons. - The SDK validates the shape, not the item names; names unknown to the platform catalog are ignored by the confirm page.
For a real manual E2E run without mocked registration responses:
python3 samples/registration/app_preset_live_e2e.py --open| Parameter | Description | Type | Required | Default |
|---|---|---|---|---|
on_qr_code |
Callback when the verification URL is ready. Receives {"url": str, "expire_in": int} |
function | Yes | - |
on_status_change |
Callback on polling status changes. Status values include polling, slow_down, domain_switched |
function | No | - |
source |
Source identifier appended to the QR URL as python-sdk/{source} |
string | No | python-sdk |
cancel_event |
threading.Event used to cancel sync polling |
threading.Event | No | - |
domain |
Custom Feishu accounts base URL | string | No | https://accounts.feishu.cn |
lark_domain |
Custom Lark accounts base URL used when tenant brand is Lark | string | No | https://accounts.larksuite.com |
app_preset |
Pre-fill values for the app-creation page. All fields are optional; users can still edit them on the page. Pass raw values; the SDK URL-encodes them automatically | dict | No | - |
app_preset.avatar |
App avatar URL(s). 1-6 URLs supported; the first one is selected by default. Allowed formats are handled by the Web page: png / jpg / jpeg / webp / gif | string or list[string] | No | - |
app_preset.name |
App name. Supports the {user} placeholder, replaced by the Web page with the scanning user's name |
string | No | - |
app_preset.desc |
App description. Supports the {user} placeholder |
string | No | - |
addons |
Incremental scopes/events/callbacks pre-filled into the confirm page, effective after user confirmation | dict | No | - |
addons.scopes.tenant |
App-identity scopes, e.g. im:message:send_as_bot |
list[string] | No | - |
addons.scopes.user |
User-identity scopes, e.g. calendar:calendar:read |
list[string] | No | - |
addons.events.items.tenant |
App-identity events, e.g. im.message.receive_v1 |
list[string] | No | - |
addons.events.items.user |
User-identity events, e.g. calendar.calendar.event.changed_v4 |
list[string] | No | - |
addons.callbacks.items |
Callbacks, e.g. card.action.trigger |
list[string] | No | - |
create_only |
When True, the landing page only allows creating a new app and hides the select-existing-app entry. Takes precedence over app_id when both are set |
bool | No | - |
app_id |
App ID (cli_ prefix) of an existing app. When set, the flow updates that app's config; carried on the QR URL as clientID |
string | No | - |
lark_oapi.channel is the legacy Channel entry point kept for compatibility
during the migration window. New Channel features ship in
lark-channel-sdk with the
lark_channel import path; critical fixes for existing lark_oapi.channel
users are evaluated for backport until 2027-06-02.
lark-channel-sdk can be installed alongside lark-oapi. Its
SecurityConfig
defaults to compatibility mode so migrated bots can roll out with audit mode
before strict enforcement. See the
migration guide
for the full checklist.
pip install lark-channel-sdkfrom lark_channel import FeishuChannelExisting legacy import example:
import asyncio
import os
from lark_oapi.channel import FeishuChannel
channel = FeishuChannel(
app_id=os.environ["LARK_APP_ID"],
app_secret=os.environ["LARK_APP_SECRET"],
)
async def on_message(msg):
await channel.send(
msg.chat_id,
{"text": f"echo: {msg.content_text}"},
)
channel.on("message", on_message)
asyncio.run(channel.connect())Channel documentation:
- Legacy Channel module
- Legacy Channel quickstart
- Legacy Channel reference
- Standalone Channel migration guide
- Standalone Channel security guide
- Runnable legacy echo bot sample
More composite API examples and business scenario samples are available in oapi-sdk-python-demo.
- Send file message
- Send image message
- List users under a department
- Create a Base app with tables
- Robot quick start
MIT
Click Server SDK in the upper right corner of the documentation page and submit feedback.