Implement member search, department management, and ID conversion via the Contact v3 API.
API Basics
Base URL: https://open.feishu.cn/open-apis/contact/v3
Authentication: Authorization: Bearer {tenant_access_token}
Authentication and Token Retrieval
From feishu_skills root directory, execute the shared script:
TOKEN="$(./scripts/get_feishu_token.sh)"
Request headers uniformly use Authorization: Bearer ${TOKEN}。
If the business API returns token invalid, expired, or 401, force refresh and retry the original request only once:
TOKEN="$(./scripts/get_feishu_token.sh --force-refresh)"
Environment Variables:
FEISHU_APP_IDFEISHU_APP_SECRET
Local Cache: ./.feishu_token_cache.json(reused directly if not expired, refreshed 5 minutes early by default)
Member Query
| API | Endpoint | Description |
|---|---|---|
| Search Members | GET /users/batch_get_id |
Get OpenID via email/phone number |
| Get Job Title | GET /job_titles/{id} |
Must be pre-maintained in the admin console |
Department Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Department | /departments/{department_id} |
GET | - | Query details of a single department |
| Get Department List | /departments |
GET | - | Supports parent_department_id parameter |
| Get Parent Department Path | /departments/{department_id}/parent |
GET | - | Get department hierarchy path |
| Create Department | /departments |
POST | {"name":"新部门","parent_department_id":"0"} |
Requires admin permission |
| Update Department | /departments/{department_id} |
PUT | {"name":"更新后的名称"} |
Modify department information |
| Delete Department | /departments/{department_id} |
DELETE | - | Delete an empty department |
| Onboard Member | /users |
POST | {"name":"张三","mobile":"138...","department_ids":["od_xxx"]} |
Create user |
| Update User | /users/{user_id} |
PUT | {"name":"新名字"} |
Modify user information |
| Delete User | /users/{user_id} |
DELETE | - | Remove user |
| Get User List | /users |
GET | - | Supports department_id filtering |
⚠️ Creating departments and onboarding members require the highest permissions; testing in a pre-release environment is recommended.
User Group Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get User Group List | /groups |
GET | - | Query all user groups |
| Get User Group | /groups/{group_id} |
GET | - | Query a single user group |
| Create User Group | /groups |
POST | {"name":"项目组","description":"描述"} |
Create a new user group |
| Update User Group | /groups/{group_id} |
PUT | {"name":"新名称"} |
Modify user group |
| Delete User Group | /groups/{group_id} |
DELETE | - | Delete user group |
| Get Group Members | /groups/{group_id}/members |
GET | - | Query group member list |
| Add Group Member | /groups/{group_id}/members |
POST | {"member_id":"ou_xxx","member_type":"user"} |
Add user to group |
| Remove Group Member | /groups/{group_id}/members/{member_id} |
DELETE | - | Remove user from group |
Job Level Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Job Level List | /job_families |
GET | - | Query all job levels |
| Get Job Level | /job_families/{job_family_id} |
GET | - | Query a single job level |
| Create Job Level | /job_families |
POST | {"name":"高级工程师"} |
Create a new job level |
| Update Job Level | /job_families/{job_family_id} |
PUT | {"name":"资深工程师"} |
Modify job level |
| Delete Job Level | /job_families/{job_family_id} |
DELETE | - | Delete job level |
Role Management
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Get Role List | /roles |
GET | - | Query all roles |
| Create Role | /roles |
POST | {"role_name":"管理员"} |
Create a new role |
| Update Role | /roles/{role_id} |
PUT | {"role_name":"超级管理员"} |
Modify role name |
| Delete Role | /roles/{role_id} |
DELETE | - | Delete role |
| Get Role Members | /roles/{role_id}/members |
GET | - | Query all members under a role |
| Batch Add Role Members | /roles/{role_id}/members/batch_create |
POST | {"members":[{"member_id":"ou_xxx","member_type":"user"}]} |
Batch add members |
| Batch Remove Role Members | /roles/{role_id}/members/batch_delete |
POST | {"members":[{"member_id":"ou_xxx"}]} |
Batch remove members |
ID Conversion (Core)
Feishu's three ID systems:
| ID Type | Description | Use Case |
|---|---|---|
open_id |
Unique within an app | Identify users within the same app |
user_id |
Unique within an enterprise | Integration with enterprise internal systems |
union_id |
Unique across apps | Across multiple apps of the same developer |
Contact v3 ID Conversion
| API | Endpoint | Method | Request Body Example | Description |
|---|---|---|---|---|
| Batch Get User IDs | /users/batch_get_id |
POST | {"emails":["a@b.com"],"mobiles":["138xxx"]} |
Get OpenID via email/phone |
| Batch Get Department IDs | /departments/batch_get_id |
POST | {"department_ids":["od_xxx"]} |
Department ID conversion |
| Get User | /users/{user_id} |
GET | - | Get user information by ID |
| Get User Information (Batch) | /users/batch_get |
GET | - | Parameters:user_ids=ou_1,ou_2 |
ID Conversion Best Practices:
Through the GET /users/{user_id} endpoint, you can retrieve all ID types of a user (open_id/user_id/union_id) at once, without the need for separate conversions.
Example:
GET /contact/v3/users/ou_xxx?user_id_type=open_id
Response includes:
{
"data": {
"user": {
"open_id": "ou_xxx",
"user_id": "7c43cd5f",
"union_id": "on_xxx"
}
}
}
Other
| API | Endpoint | Method | Description |
|---|---|---|---|
| Get Job Title List | /job_titles |
GET | Query all preset job titles |
| Get Job Title | /job_titles/{job_title_id} |
GET | Query details of a single job title |
| Get Office Location | /places |
GET | Used for personnel geographic distribution analysis |
| Get Employee Type | /employee_types |
GET | Query employee type list |
| Get Custom Attributes | /custom_attr_events |
GET | Query custom attribute change events |
| Get Authorization Scope | /scopes |
GET | Query the department/user scope accessible to the app |
| External Member Access | /application/v1/applications/{app_id}/user_usable |
GET | Control vendor/outsourced access permissions |
Event Subscription
The contact directory supports 17 change events:
| Event Type | Description |
|---|---|
contact.user.created_v3 |
User created |
contact.user.updated_v3 |
User information updated |
contact.user.deleted_v3 |
User deleted |
contact.dept.created_v3 |
Department created |
contact.dept.updated_v3 |
Department updated |
contact.dept.deleted_v3 |
Department deleted |
contact.employee_type.created_v3 |
Employee type created |
contact.employee_type.updated_v3 |
Employee type updated |
contact.employee_type.deleted_v3 |
Employee type deleted |
contact.job_family.created_v3 |
Job level created |
contact.job_family.updated_v3 |
Job level updated |
contact.job_family.deleted_v3 |
Job level deleted |
Best Practices
- Prefer Spark API for ID conversion(more concise)
- Cache frequently used IDs(Reduce API calls)
- Organizational structure changes must be pre-release tested