获取部门列表
分页获取指定父部门下的直接子部门列表。
接口信息
| 项目 | 说明 |
|---|---|
| 接口名称 | 获取部门列表 |
| 权限标识 | contact.department.read(读取组织架构) |
| 请求方式 | POST / GET |
| 请求地址 | https://{gateway_host}/open/v1/contact/department/list |
| 数据格式 | application/json(POST 时)或 URL Query |
| 鉴权方式 | 应用级 access_token(需具备 contact.department.read 权限) |
前置条件
- 应用已在管理后台「内部应用」中发布并启用。
- 已获取有效的应用级凭证
access_token。 - 查询的父部门必须存在且处于应用的可见范围之内。
请求参数
请求头
| 请求头 | 必填 | 说明 |
|---|---|---|
Authorization | 否 | Bearer <access_token>,推荐的凭证传递方式(与 Query / 表单三选一) |
Content-Type | 否 | POST 请求使用 JSON 时传 application/json |
参数列表
参数支持在 POST JSON Body、POST Form 表单或 GET Query 中传递:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
access_token | string | 是 | 应用级令牌(若未在 Authorization 头中携带,则必填) |
dept_id | string | 否 | 父部门 ID。省略或传 "0" 时返回应用可见范围内的顶层部门/根部门 |
cursor | string | 否 | 分页游标,从 0 开始的数字偏移量,默认 0。系统兼容别名 next_cursor、nextCursor |
size | integer | 否 | 每页返回数量,取值范围 1–100,默认 100 |
language | string | 否 | 语言/国际化预留参数,当前不影响返回内容 |
请求示例
POST 请求示例:
POST https://{gateway_host}/open/v1/contact/department/list
Authorization: Bearer <access_token>
Content-Type: application/json
{
"dept_id": "0",
"cursor": "0",
"size": 50
}
GET 请求示例:
GET https://{gateway_host}/open/v1/contact/department/list?dept_id=0&cursor=0&size=50
Authorization: Bearer <access_token>
响应参数
成功响应(平台统一响应外壳):
{
"code": 200,
"msg": "",
"data": {
"departments": [
{
"deptId": "20",
"name": "研发部",
"parentId": "10",
"order": 1
},
{
"deptId": "30",
"name": "市场部",
"parentId": "10",
"order": 2
}
],
"hasMore": true,
"nextCursor": "2"
}
}
| 字段 | 类型 | 说明 |
|---|---|---|
code | integer | 业务状态码,200 表示成功 |
msg | string | 提示信息,成功时为空 |
data.departments | object[] | 直接子部门列表 |
data.departments[].deptId | string | 部门 ID |
data.departments[].name | string | 部门名称 |
data.departments[].parentId | string | 上级部门 ID(上级不在可见范围内时截断为 "0") |
data.departments[].order | integer | 同级排序权重 |
data.hasMore | boolean | 是否还有更多数据(true 表示未遍历完,false 表示已结束) |
data.nextCursor | string | 下一页分页游标。仅在 hasMore 为 true 时返回,后续请求作为 cursor 传入 |
遍历与组织树读取建议
- 单层获取:本接口仅返回指定部门的直接下级部门,不会递归展开整棵树。
- 完整遍历组织架构推荐流程:
- 步骤 1:调用本接口并传
dept_id="0",获取应用可见范围内的所有顶层部门; - 步骤 2:对每个部门递归调用本接口,逐层向下遍历读取子部门;
- 步骤 3:结合《获取部门成员列表》接口读取每个部门的直属成员,组装完整的通讯录数据。
- 步骤 1:调用本接口并传
- 分页结束标记:请以
hasMore == false作为循环终止条件。
可见范围与组织遍历
应用可见范围同时影响工作台展示、免登和通讯录返回结果。范围之外的成员或部门按不存在处理。
推荐遍历顺序
- 不传
dept_id调用《获取部门列表》,得到可见范围内的顶层节点。 - 对每个部门递归调用部门列表接口,直到没有子部门。
- 对每个部门调用获取部门成员列表并按
userId归并。 - 使用事件订阅获取变化信号,并定期全量对账。
语义约束
parentId="0"可能只是可见范围下的顶层节点,不一定是真实企业根节点。- 可见范围变更后,后续请求立即按新范围过滤,不需要重新换取
access_token。 - 成员可能属于多个部门,
deptIdList只包含应用可见部门。 - 分页以
hasMore为准,不能以当前页数量是否小于size判断结束。
组织遍历示例
Shell
# 中文注释:先读取顶层部门,再把 nextCursor 原样传回下一页。
curl -sS -X POST "https://{gateway_host}/open/v1/contact/department/list" -H "Authorization: Bearer access-token-xxx" -H "Content-Type: application/json" -d '{"cursor":"0","size":100}'
PHP
<?php
// 中文注释:生产代码应使用队列遍历部门,避免递归深度不可控。
$url = 'https://{gateway_host}/open/v1/contact/department/list?cursor=0&size=100'; $ch = curl_init($url); curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_HTTPHEADER => ['Authorization: Bearer access-token-xxx'], CURLOPT_RETURNTRANSFER => true]); echo curl_exec($ch); curl_close($ch);
Golang
package main
import "net/http"
func main() {
// 中文注释:实际同步应使用队列和 userId 去重,避免成员多部门重复入库。
request, _ := http.NewRequest(http.MethodPost, "https://{gateway_host}/open/v1/contact/department/list?cursor=0&size=100", nil); request.Header.Set("Authorization", "Bearer access-token-xxx"); response, _ := http.DefaultClient.Do(request); defer response.Body.Close()
}
C++
#include <curl/curl.h>
int main() {
// 中文注释:不要硬编码唯一根部门 ID,应以接口返回的顶层节点为起点。
CURL* handle = curl_easy_init(); struct curl_slist* headers = curl_slist_append(nullptr, "Authorization: Bearer access-token-xxx"); curl_easy_setopt(handle, CURLOPT_URL, "https://{gateway_host}/open/v1/contact/department/list?cursor=0&size=100"); curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(handle, CURLOPT_POST, 1L); const CURLcode result = curl_easy_perform(handle); curl_slist_free_all(headers); curl_easy_cleanup(handle); return result == CURLE_OK ? 0 : 1;
}
事件只表示“可能发生变化”,不能替代最终查询;详见事件订阅。
数据规则
- 可见范围之外的数据按不存在处理,应用不能通过错误码区分“不存在”和“不可见”。
- 部门列表返回直接子部门,成员列表返回直属成员;完整同步按可见范围与组织遍历执行。
- 成员 ID、部门 ID 使用字符串;未设置的可选字段可能不返回。
- 列表接口使用
cursor、size、hasMore和nextCursor翻页。
公共错误码和重试规则见接入指南。
错误码说明
鉴权与中间件错误(HTTP 状态码)
| HTTP 状态码 | msg 错误码 | 说明 |
|---|---|---|
| 401 | INVALID_TOKEN | 令牌缺失、已过期、已失效,或应用不可用 |
| 403 | SCOPE_DENIED | 令牌缺少 contact.department.read 权限 |
| 403 | IP_DENIED | 请求来源 IP 未命中应用安全设置的 IP 白名单 |
业务错误(HTTP 200,code=500)
{
"code": 500,
"msg": "DEPARTMENT_NOT_FOUND",
"data": null
}
msg 错误码 | 说明与排查建议 |
|---|---|
INVALID_REQUEST | 参数 cursor 不是合法的数字偏移量或超出范围;size 不在 1–100 区间内 |
DEPARTMENT_NOT_FOUND | 指定的父部门 dept_id 不存在、已被删除或不在应用可见范围内 |
PERMISSION_DENIED | 应用状态异常(已被停用、取消发布或删除) |
SERVER_ERROR | 服务端内部异常,请稍后重试 |
多语言调用示例
以下示例使用服务端调用方式;应用密钥和应用令牌不得下发到客户端。
Shell
curl -sS -X POST "https://{gateway_host}/open/v1/contact/department/list" \
-H "Authorization: Bearer access-token-xxx" \\\n -H "Content-Type: application/json" \
-d '{"dept_id":"0","cursor":"0","size":50}'
PHP
<?php
// 中文注释:生产环境应检查 HTTP 状态码和响应体,再映射业务错误。
$handle = curl_init('https://{gateway_host}/open/v1/contact/department/list');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer access-token-xxx', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"dept_id":"0","cursor":"0","size":50}',
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($handle);
curl_close($handle);
Golang
package main
import (
"bytes"
"net/http"
)
func main() {
// 中文注释:令牌只在服务端请求中使用,并按接口约定携带。
request, _ := http.NewRequest(http.MethodPost, "https://{gateway_host}/open/v1/contact/department/list", bytes.NewBufferString(`{"dept_id":"0","cursor":"0","size":50}`))
request.Header.Set("Authorization", "Bearer access-token-xxx")
request.Header.Set("Content-Type", "application/json")
response, _ := http.DefaultClient.Do(request)
defer response.Body.Close()
}
C++
#include <curl/curl.h>
int main() {
// 中文注释:生产环境应启用 TLS 校验并处理 HTTP 错误。
CURL* handle = curl_easy_init();
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Authorization: Bearer access-token-xxx");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(handle, CURLOPT_URL, "https://{gateway_host}/open/v1/contact/department/list");
curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, R"({"dept_id":"0","cursor":"0","size":50})");
const CURLcode result = curl_easy_perform(handle);
curl_slist_free_all(headers);
curl_easy_cleanup(handle);
return result == CURLE_OK ? 0 : 1;
}