服务端 API/通讯录/常见问题
# 通讯录常见问题

使用「通讯录」相关API时遇到的常见问题
根据右侧导航栏中的问题分类可快速查找相关问题

## 如何高效地使用通讯录接口

答：通讯录模块目前包含成员、部门、用户组等几大模块，每个模块都会提供对应的api接口，便于开发者进行智能化的系统对接。开发者对于接口的使用权限主要分为**三类**：<br><br>
1、接口的使用权限。定义应用有无权限调用该接口。<br>
2、接口操作的数据权限。定义应用能否对某些数据进行查询或操作。<br>
3、数据字段的权限。由于某些实体（如用户）不同字段的敏感度不同，如用户的手机号，相对比较敏感，要获取就需要额外的权限。<br><br>基于上述三个权限的认知，开发者在进行开发时，可以自行检查，提高开发效率。自行检查确认点为：
1. 调用某接口时是否有接口的调用权限，如果没有，接口无法访问；
2. 获取或操作某数据时，是否有该数据的通讯录权限，如果没有，会提示无权限；
3. 获取某实体的具体字段时是否有该字段的权限，如果没有，可能会获取不到。

#### ***开发示例说明***
> 开发者希望通过 [创建用户](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/create) 接口，向企业中添加用户。<br>开发者需要首先确认是否有接口的访问权限，此处为“更新通讯录”的权限；确认完接口权限后，由于需要将用户添加到某个（或某几个）部门下，因此需要确认是否有待加入部门的通讯录权限，如果没有待加入部门的通讯录权限，是无法操作添加的；创建完返回或通过 ID 获取用户信息的时候，用户的敏感字段，开发者想要获取，需确认有无敏感字段的权限。<br>

## 通讯录权限范围相关问题

**Q：user_accss_token 与 tenant_access_token 在访问通讯录接口时权限有什么区别**

答：二者使用获取或操作数据时权限过滤范围不一样。
1. **tenant_access_token** 基于应用的通讯录范围进行权限的过滤，如调用接口获取部门 A 时，会检查部门 A 是否在应用的通讯录权限范围内。其规则配置入口为：Admin管理后台/工作台管理/应用管理。
2. **user_accss_token** 基于用户的可见组织架构范围来做权限过滤，用户可见的组织架构范围为app端上“通讯录”--“组织架构”部分可见的架构，其规则配置入口为：登陆[Admin管理后台](https://www.larksuite.com/admin),进入“安全”--“用户权限”--“组织架构可见范围”。

<br>
**Q：如何获取企业全部员工信息？**

答：Lark目前没有单独的接口可以获得全部员工信息，如果需要获取，可以按照以下的步骤操作确认：<br>
1、确认应用通讯录范围是否为全员，请保证开启为全员。如果不是全员，可能无法获取到全员信息。<br>
2、确认通讯录范围为全员后，通过[获取部门信息列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/department/list)接口，设置参数parent_department_id=0，fetch_child=true。获取企业下所有部门ID列表。<br>
3、在步骤2获取部门ID列表的基础上，通过[获取用户列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/list)等接口搭配使用，来获得全部员工的相关信息。
<br>
<br>

**Q：如何获取根部门下的员工通讯录信息？**

答：首先请确保应用的通讯录权限范围设置为“全员”或包含根部门下的所有员工，然后通过[获取用户列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/list)接口，设置参数department_id=0，获得根部门下的员工通讯录信息。
<br>
<br>

## ID类问题
**Q：设定好了权限及权限使用的范围，但是仍然获取不到user_id、邮箱、手机号等信息**

答：这里因为==user_id==、邮箱、手机号等信息比较敏感，需要单独申请相应的权限，无法仅仅通过“获取用户信息权限”这一个权限来获得。详情请参考[应用权限](https://open.larksuite.com/document/ukTMukTMukTM/uQjN3QjL0YzN04CN2cDN)文档。
<br>
<br>

**Q：同一个用户在多个应用的 open_id 是一样的吗？**

答：不一样。==open_id== 是用户在应用内唯一标识，因此同一个用户在不同应用中的 ==open_id== 不一致
<br>
<br>

**Q：用户在不同企业的 open_id 和 union_id 是不是一样的？**

答：不一样。不同的企业内的用户应算作两个用户，因此进行区分
<br>
<br>

**Q：user_id（employee_id） 能不能更新呢？**

答：你可以在创建用户将该用户在企业内部系统已存在的唯一 ID 指定为==user_id==，若不指定将由系统自动为用户生成一个唯一的随机 ID 作为==user_id==，已创建用户的 ==user_id==（部分场景也叫 employee_id）不支持更新，因为各应用方都可能用到并保存 ==user_id==, 如果修改 ==user_id== 可能造成应用感知不到，从而造成应用无法使用等问题。
<br>
<br>

**Q：user_id 如何获取？**
答：可以通过email或mobile换取，换取方式见接口[使用手机号或邮箱获取用户 ID](https://open.larksuite.com/document/ukTMukTMukTM/uUzMyUjL1MjM14SNzITN) 或者 登录[管理后台](https://www.larksuite.com)，点击用户详情，查看获取“用户 ID”。

## 用户/人员相关问题

**Q：我一不小心误删了部门（或者人员），能不能按照原有的 ID 进行恢复？**

答：目前不能恢复原有的ID。企业的 ID 是唯一的，建议新增一个 ID。
<br>
<br>

**Q：我不明白人员的status字段，有详细的注解吗？**

答：可以将该字段对应的数字转化为二进制，对应位数就是对应的值的状态。对照：bit0(最低位): 1冻结，0未冻结；bit1：1离职，0在职；bit2：1未激活，0已激活
例：数字“2”转化为二进制就是“010”，意味着“已激活、离职、未冻结”；而数字“0”转化为二进制就是“000”，意味着“已激活、在职、未冻结”。
<br>
<br>

**Q：我开发了多个应用，想知道其中某个应用的用户是否也在使用我开发的其他应用。可以通过什么字段来判断？**

答：目前可以使用字段 ==union_id==，一个用户在同一个开发者所属的多个应用中，==union_id== 唯一
<br>
<br>

**Q：[搜索用户](https://open.larksuite.com/document/ukTMukTMukTM/uMTM4UjLzEDO14yMxgTN) 接口为什么获取不到返回值？**

答： 你可以通过以下方式排查原因：<br>
-  确认你能在Lark客户端的搜索栏中搜到对应用户，且该用户不是外部用户或离职人员
-  确认请求参数 ==page_token== 的值是否正确 
<br>
<br>

**Q：调用手机号或邮箱获取用户 ID/获取用户信息接口时，为什么只能获取自己的，不能获取其他人员的？**

答：请确认相关应用的[通讯录权限范围](https://open.larksuite.com/document/ukTMukTMukTM/uETNz4SM1MjLxUzM/v3/guides/scope_authority)包含包含要获取的用户，而不是只有你自己，如果通讯录范围不包含获取的用户，会返回邮箱或手机号不存在。
<br>
<br>

**Q：人员为什么有时候会被拉入其他的部门群？**

答： 可以通过如下步骤排查：
- 确认用户是否有反复修改部门
- 确认该人员是不是被拉入的部门的负责人
<br>
<br>

**Q：系统默认生成的userid，业务方保存userid，删除A员工之后，这个userid会不会被后面新增的员工占用?**

答：系统默认生产成的 ==userid== ，保证了企业内有效（无效表示已离职用户）用户唯一，开发者或管理员对用户进行删除，添加，可能会存在新添加的用户的 ==userid== 和历史上已经删除的用户一样。所以建议增加用户的时候，用具有唯一性标示的id作为 ==userid== ，避免造成困扰（注：部门的自定义ID同理）。
<br>
<br>

## 用户接口相关问题

**Q： [创建用户接口](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/create) 或者 [获取单个用户信息](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/get) 接口请求或应答的结构体内的自定义字段应该如何理解？**

答：用户的 ==custom_attrs== 属性是对用户属性的扩展，用于企业根据自身需求灵活扩展用户描述能力，根据取值语法的不同主要分为文本类型、网页类型、枚举类型、图片类型、用户类型。<br>
**文本类型**：类用户的 ==name== 属性，只有一个 string 类型的 value。值对应 ==text== 字段<br>
**网页类型**: 字段引用链接，可在成员名片页实现点击跳转效果。该类型字段需要有标题文字，值对应 ==text== 字段，需要有跳转的 url ，值对应 ==url== 。由于PC 端的跳转链接可能会和移动端不太一样，所以单独设置了 ==pc_url== 作为跳转的url，如果该值不填，则 PC 端链接使用 ==url==。<br>
**枚举类型：** 实现字段取值在给定选项中选择，如员工类型，包含正式、外包、顾问。企业成员的员工类型，只能在这些选项中选择，该类型的值对应 ==option_id== ，也就是管理员配置的某个选项 key 。<br>
**图片类型** 与枚举类型相似，只是选项的数据类型只能是图片，用于在成员名片页展示其对应的图片，该类型的值对应 ==option_id==，可从管理后台查询对应的图片id。<br>
**用户类型** 该类型主要用于成员名片页展示对另一用户的引用，实现成员名片页之间的跳转，如将“张三”的 HRBP 字段显示“李四”并支持点击跳转至李四的名片页。对应generic_user 下 id 为需要引用的成员 user_id, generic_user 下的 type 目前固定为1,表示用户类型。<br>

**特殊说明：**
请确保你的组织管理员已在 [管理后台/组织架构/成员字段管理/自定义字段管理/全局设置](http://www.larksuite.com/admin/contacts/employee-field-new/custom) 中开启了“允许开放平台 API 调用“，否则该字段不会生效/返回。如果创建或更新需要对用户新加自定义字段的值，请确保自定义字段的 key 已经被企业管理员创建且有效。
<br>

<br>
**Q：[创建用户接口](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/create)企业邮箱字段 enterprise_email 该如使用？**

答：创建用户接口中 ==enterprise_email== 字段表示设置用户的企业邮箱，由于企业邮箱的域名需要企业在管理后台申请并开启。如果企业没有开启对应域名的企业邮箱，设置用户的企业邮箱会操作失败，请联系企业的管理员确认企业是否在后台启用了该域名的企业邮箱。
<br>
<br>

**Q：如何理解 [获取用户列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/list) 接口？**

答：该接口的设计含义是获取某个部门下的直属用户列表，由于数据的获取受到通讯录权限范围的检查，如果请求带上了部门ID（根部门的部门ID为0），首先会检查应用是有该部门ID的通讯录权限，如果有，就会返回该部门下的直属成员信息（如果带上了==department_id=0== 表示 check 有没有根部门的通讯录权限，有的话，返回根部门下直属成员信息）；如果请求没有带上部门 ID,无法进行 ID 的通讯录权限校验，就会获取到权限范围内的独立成员（当权限范围包含了某成员，但不包含成员所在部门，则该成员视为权限范围内的独立成员）。所以开发者在使用该接口时，应该结合通讯录的权限以及要获取的数据，来决定如何使用，要不要带部门 ID。
<br>
<br>
## 部门接口相关问题

**Q：如何获取父部门下所有员工的通讯录信息？**

答：目前不能通过一个接口来获取父部门下所有员工的通讯录信息，需要通过[获取部门信息列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/department/list)接口获取父部门下所有部门的==department_id==，然后通过[获取用户列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/user/list)接口获取每个部门下员工的通讯录信息。
<br>
<br>

**Q：为什么获取[获取部门信息](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/department/get)接口获取到 department_id 有时候返回的带 od-，有时候不带？**

答：确认请求是否指定了不同的 ==department_id_type== ，若没指定，默认是open_department_id。

<br>
**Q：如何理解获取 [获取部门信息列表](https://open.larksuite.com/document/uAjLw4CM/ukTMukTMukTM/reference/contact-v3/department/list) 接口？**

答：接口语义是获取部门下的子部门信息，由于数据的获取受到通讯录权限范围的检查，如果请求带上了父部门 ID（根部门的部门 ID 为0），首先会检查应用是有该部门 ID 的通讯录权限（如果带上了0，会校验是否有全员权限），如果有，就会返回该部门下部门（根据 ==fetch_child== 为 ==true== 或 ==false== 来决定是否递归）信息；如果请求没有带上父部门 ID,无法进行 ID 的通讯录权限校验，就会根据通讯录权限范围返回数据，如果通讯录范围是全员，就会返回单个根部门 ID 0（开发者可以通过根部门 id 继续请求），否则返回通讯录范围的部门信息。所以开发者在使用该接口时，应该结合通讯录的权限以及要获取的数据，来决定如何使用，要不要带父部门 ID。

<br>
<br>

## 错误排查

**Q：使用批量获取信息接口的时候，只返回了部分信息，没有返回全部批量信息。但为什么接口仍会提示任务执行成功， msg 也会返回“success”？**

答：批量接口的返回值是指当前批量任务的执行情况，意味是否执行，而非是否执行成功。只要能开始执行都会记为“执行”。详细的执行情况可以参考[查询批量任务执行状态](https://open.larksuite.com/document/ukTMukTMukTM/uUDOwUjL1gDM14SN4ATN)文档。
<br>
<br>

**Q：40013 param error 有哪些情况？**

答：可以通过如下步骤排查：
- 检查一下对应员工/部门的状态，有没有离职 /被删除；
- 参数错误，具体错误原因可参考 message 信息和表下面的补充，如有疑问，请联系管理员；
- 手机号已存在，检查手机号是否重复； 
- 手机号和邮箱冲突，检查对应的手机号和邮箱有没有分属于两个不同的Lark账号，如果存在就需要修改其中一个手机号/邮箱，或者注销掉其中一个账号；  
- 更新时目标部门下是否有同名部门；
- 不能更新子部门作为父部门；
- 自定义文本字段超过默认的100长度限制
<br>
<br>

**Q：[新增用户](https://open.larksuite.com/document/ukTMukTMukTM/uMzNz4yM3MjLzczM)返回 email and mobile account conflict 的解决方案？**

答：手机号和邮箱分别注册了两个不同的账号后，手机号和邮箱实际上是对应登录凭证不同的两个账号。在新增用户时同时设置了之前的手机号和邮箱，就会将手机号和邮箱同时作为登录凭证关联到一个账号，但是之前邮箱和手机号分别在Lark注册了是两个不同的凭证，就会报上面的错误。解决方案是新增的时候只设置手机号，再去更新邮箱，这样邮箱只是作为一个“属性”而不是登录凭证，或者引导用户注销掉其中一个账号。
<br>
<br>

**Q：[新增用户](https://open.larksuite.com/document/ukTMukTMukTM/uMzNz4yM3MjLzczM)返回 department id xxxxxxxx is not exist 的原因？**

答：原因一般有如下三个：
- 写入的 ==department id== 不存在
- ==open_department_id== 和 ==department_id== 是两个不同的 id，是否使用了 ==open_department_id== 
- 应用不在该部门的通讯录权限范围内
<br>