Skip to main content

List Department Members

Get a paginated list of direct members under the specified department.

API information​

ItemDescription
API nameList Department Members
Permission scopecontact.department.read(read organization structure)
HTTP methodPOST / GET
Endpointhttps://{gateway_host}/open/v1/contact/user/list
Data formatapplication/json(for POST) or URL query
AuthenticationApp-level access_token(requires contact.department.read permission)

Prerequisites​

  1. The app has been published and enabled under "Internal Apps" in the admin console.
  2. A valid app-level access_token has been obtained.
  3. The department must be within the app's visibility scope.

Request parameters​

HeaderRequiredDescription
AuthorizationNoBearer <access_token>,recommended credential transport method; choose it instead of query or form authentication
Content-TypeNoSend application/json when a POST request uses JSON

Parameter list​

Parameters may be sent in a POST JSON body, POST form, or GET query:

ParameterTypeRequiredDescription
access_tokenstringYesApp-level token(if it is not sent in the Authorization header, it is required)
dept_idstringYesDepartment ID (a positive integer string). Required; it cannot be omitted. If the app is authorized for a single root department, pass "1" as the root mapping. The system also accepts aliases deptId, departmentId, and department_id
cursorstringNoPagination cursor, a numeric offset starting at 0 and defaulting to 0.The system also accepts aliases next_cursor, nextCursor
sizeintegerNoNumber of members per page, from 1 to 100, default 100
languagestringNoReserved localization parameter; it currently does not affect the response

Request examples​

POST Request examples:

POST https://{gateway_host}/open/v1/contact/user/list
Authorization: Bearer <access_token>
Content-Type: application/json

{
"dept_id": "20",
"cursor": "0",
"size": 50
}

GET Request examples:

GET https://{gateway_host}/open/v1/contact/user/list?dept_id=20&cursor=0&size=50
Authorization: Bearer <access_token>

Response parameters​

Successful response (the platform's unified response envelope):

{
"code": 200,
"msg": "",
"data": {
"users": [
{
"userId": "42",
"name": "Zhang San",
"avatar": "https://cdn.example.com/avatar/42.png",
"mobile": "13800000000",
"email": "zhangsan@example.com",
"jobNumber": "A-001",
"title": "Engineer",
"deptIdList": ["10", "20"]
}
],
"hasMore": true,
"nextCursor": "1"
}
}
FieldTypeDescription
codeintegerBusiness status code; 200 indicates success
msgstringMessage; empty on success
data.usersobject[]Member list; [] when there are no members. Fields match the Get Member Details API
data.users[].userIdstringmember ID
data.users[].namestringMember nickname/name
data.users[].avatarstringAvatar URL; omitted when not set
data.users[].mobilestringMobile number; omitted when not set
data.users[].emailstringEmail address; omitted when not set
data.users[].jobNumberstringEmployee number; omitted when not set
data.users[].titlestringJob title; omitted when not set
data.users[].deptIdListstring[]List of department IDs for the member (visible departments only)
data.hasMorebooleanWhether more member data is available
data.nextCursorstringCursor for the next page; returned only when hasMore is true, and sent as cursor in the next request

Return rules and notes​

  1. Direct members, no recursion: This API returns only members directly belonging to the department and does not recursively expand child-department members. To get child-department members, first use the department-list API to obtain child department IDs, then call this API for each department.
  2. Complete fields, no second query: Returned member objects contain all public member fields, so traversal does not need an additional detail call for every member.
  3. Visibility-scope filtering: Only active members within the app's visibility scope are returned. A member directly belonging to the department is omitted when the app is not authorized to see that member.
  4. Pagination termination: Strictly use hasMore and nextCursor to determine whether pagination is complete; do not use whether the current page count is less than size.

Error codes​

Authentication and middleware errors (HTTP status)​

HTTP statusmsg Error codeDescription
401INVALID_TOKENThe token is missing, expired, revoked, or the app is unavailable
403SCOPE_DENIEDThe token lacks contact.department.read permission
403IP_DENIEDThe source IP is not in the IP allowlist configured in the app security settings

Business errors (HTTP 200, code=500)​

{
"code": 500,
"msg": "DEPARTMENT_NOT_FOUND",
"data": null
}
msg error codeDescription and troubleshooting guidance
INVALID_REQUESTParameter dept_id is missing, empty, or not a valid positive integer; cursor is malformed; or size is outside 1–100
DEPARTMENT_NOT_FOUNDThe department does not exist, has been deleted, or is outside the app's visibility scope
PERMISSION_DENIEDThe app state is invalid (disabled, unpublished, or deleted)
SERVER_ERRORInternal server error; retry later

Multilingual call examples​

The following examples run on the server; never send app secrets or app tokens to a client.

Shell​

curl -sS -X POST "https://{gateway_host}/open/v1/contact/user/list" \
-H "Authorization: Bearer access-token-xxx" \\\n -H "Content-Type: application/json" \
-d '{"dept_id":"20","cursor":"0","size":50}'

PHP​

<?php
// Production code should check the HTTP status and response body before mapping business errors.
$handle = curl_init('https://{gateway_host}/open/v1/contact/user/list');
curl_setopt_array($handle, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => ['Authorization: Bearer access-token-xxx', 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => '{"dept_id":"20","cursor":"0","size":50}',
CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($handle);
curl_close($handle);

Golang​

package main

import (
"bytes"
"net/http"
)

func main() {
// Use the token only in a server-side request and follow the API transport contract.
request, _ := http.NewRequest(http.MethodPost, "https://{gateway_host}/open/v1/contact/user/list", bytes.NewBufferString(`{"dept_id":"20","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() {
// Enable TLS verification and handle HTTP errors in production.
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/user/list");
curl_easy_setopt(handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(handle, CURLOPT_POSTFIELDS, R"({"dept_id":"20","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;
}