Skip to content

Get Group

Overview

You can use the API to retrieve group records.

Preparations

Please create an "API Key" before performing any API operations.

Request

Send json data in the following request format:

Setting column Value
HTTP Method POST
Content-Type application/json
Character Code UTF-8
URL http://{server name}/api/groups/get (*1)
Body Refer to the json data below

(*1) Please edit the {server name} part to suit your environment as appropriate.
For Pleasanter.net, the format is as follows:
https://pleasanter.net/fs/api/groups/get

JSON
{
    "ApiVersion": 1.1,
    "ApiKey": "sad610bHDo04720DoloA356...",
    "View": {
        "ColumnFilterHash": {
            "GroupId": "[11,12]"
        }
    }
}

The GroupId filter is an array that allows multiple values ​​to be specified, so please write it as shown above.

Response

JSON data in the format below will be returned for the number of GroupIds selected. Please refer to here for the data layout.

JSON
{
    "StatusCode": 200,
    "Response": {
        "Offset": 0,
        "PageSize": 200,
        "TotalCount": 2,
        "Data": [
            {
                "TenantId": 1,
                "GroupId": 11,
                "Ver": 1,
                "GroupName": "Group A",
                "Body": "",
                "Disabled": false,
                "Comments": "[]",
                "Creator": 1,
                "Updator": 1,
                "CreatedTime": "2023-04-01T12:00:00",
                "UpdatedTime": "2023-08-15T12:00:00",
                "GroupMembers": [
                    "User,1,True",
                    "User,2,False",
                    "Dept,1,True"
                ],
                "GroupChildren": [
                     "Group,1,"
                ],
                "ApiVersion": 1.1,
                "ClassHash": {
                },
                "NumHash": {
                },
                "DateHash": {
                },
                "DescriptionHash": {
                },
                "CheckHash": {
                },
                "AttachmentsHash": {
                }
            }
        ]
    }
}

Code Samples

Modify 【 ... 】 in the code as necessary.
1. Read CSV files from an external system and import groups

This sample generates a CSV file for import
based on CSV files output from an external system, and imports it with the API.

Overview

It receives the user and organization information of an external system as CSV files,
and creates or updates groups with the Pleasanter Import Groups API.

The process flow is as follows.

  1. Read the input CSV files
  2. Get the existing groups from Pleasanter (/api/groups/get)
  3. Identify the existing groups by group name
  4. Generate the CSV file for the group import
  5. Run the Import Groups API (/api/groups/import)

Prerequisites

The users are already registered in Pleasanter
Group names are unique (used to decide whether to create or update)

Input Files

There are three input files, assumed to come from an external system.

input/
 ├ groups.csv
 ├ users.csv
 └ user_group_memberships.csv
groups.csv

A CSV file that defines the group information.

Column name Description
group_code Group identification code
group_name Group name
is_active 1: Enabled / 0: Disabled
remark Description

Sample

group_code,group_name,is_active,remark
GRP_ADMIN,Administration Headquarters,1,Administration division
GRP_SALES,Sales Headquarters,1,Sales division
users.csv

A CSV file that defines the user information.

Column name Description
user_id User identification ID
login_id Pleasanter login ID
user_name User name
mail Mail address
is_active 1: Enabled / 0: Disabled

Sample

user_id,login_id,user_name,mail,is_active
0001,yamada.taro,Taro Yamada,yamada@example.co.jp,1
0002,sato.hanako,Hanako Sato,sato@example.co.jp,1
user_group_memberships.csv

A CSV file that defines which groups the users belong to.

Column name Description
user_id User ID
group_code Group code
is_active 1: Enabled / 0: Disabled
is_group_admin 1: Group administrator / 0: Regular member

Sample

user_id,group_code,is_active,is_group_admin
0001,GRP_ADMIN,1,1
0002,GRP_ADMIN,1,0

Output File

The following CSV file is generated.

output/
 └ groups_import.csv

The format of the CSV file follows the specifications of Group Management Function: Import/Export.

Python(api_group_import.py)
import csv
import json
from pathlib import Path

import requests


# ==============================
# Pleasanter connection settings
# ==============================
BASE_URL = "【URL】"
API_KEY = "【API key】"
API_VERSION = 1.1
ENCODING = "UTF-8"

# True : Generate the CSV file only
# False: Generate the CSV file and then run the import
DRY_RUN = True


# ==============================
# File settings (change them as appropriate for your environment)
# ==============================
INPUT_DIR = Path("./input")
OUTPUT_DIR = Path("./output")
GROUPS_CSV = INPUT_DIR / "groups.csv"
USERS_CSV = INPUT_DIR / "users.csv"
MEMBERSHIPS_CSV = INPUT_DIR / "user_group_memberships.csv"
GROUP_IMPORT_CSV = OUTPUT_DIR / "groups_import.csv"


# ==============================
# CSV input/output settings (change them as appropriate for your environment)
# ==============================
def read_csv(path):
    with open(path, "r", encoding="utf-8-sig", newline="") as f:
        return [
            {k.strip(): (v or "").strip() for k, v in row.items()}
            for row in csv.DictReader(f)
        ]


def write_csv(path, headers, rows):
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w", encoding="utf-8-sig", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=headers)
        writer.writeheader()
        writer.writerows(rows)


def is_active(row):
    return str(row.get("is_active", "1")) == "1"


def to_disabled(row):
    return "0" if is_active(row) else "1"


def to_group_admin(row):
    return "1" if str(row.get("is_group_admin", "0")) == "1" else "0"


# ==============================
# Pleasanter API operations
# ==============================
def post_json(url, payload):
    r = requests.post(
        url,
        json=payload,
        headers={"Content-Type": "application/json"},
    )
    r.raise_for_status()
    return r.json()


# ==============================
# File upload operations
# ==============================
def post_file(url, params, file_path):
    with open(file_path, "rb") as f:
        files = {"file": (file_path.name, f, "text/csv")}
        data = {"parameters": json.dumps(params)}
        r = requests.post(url, data=data, files=files)
    r.raise_for_status()
    return r.json()


# ==============================
# Create a dictionary to check whether a group is already registered
# ==============================
def get_existing_groups():
    data = post_json(
        f"{BASE_URL}/api/groups/get", {"ApiVersion": API_VERSION, "ApiKey": API_KEY}
    )

    groups = {}
    for row in data["Response"]["Data"]:
        groups[row["GroupName"]] = row
    return groups


# ==============================
# Create the row data for the CSV file
# ==============================
def build_rows(groups, users, memberships, existing_groups):
    users_by_id = {u["user_id"]: u for u in users}
    groups_by_code = {g["group_code"]: g for g in groups}
    rows = []

    # Rows for the groups themselves
    for group in groups:
        current = existing_groups.get(group["group_name"], {})
        rows.append(
            {
                "グループID": str(current.get("GroupId", "")),
                "グループ名": group["group_name"],
                "説明": group.get("remark", ""),
                "メンバー種別": "",
                "メンバーキー": "",
                "メンバー名": "",
                "メンバーは管理者": "0",
                "無効": to_disabled(group),
            }
        )

    # Rows for the members
    for membership in memberships:
        if not is_active(membership):
            continue

        group = groups_by_code[membership["group_code"]]
        user = users_by_id[membership["user_id"]]
        current = existing_groups.get(group["group_name"], {})

        rows.append(
            {
                "グループID": str(current.get("GroupId", "")),
                "グループ名": group["group_name"],
                "説明": group.get("remark", ""),
                "メンバー種別": "User",
                "メンバーキー": user["login_id"],
                "メンバー名": user["user_name"],
                "メンバーは管理者": to_group_admin(membership),
                "無効": to_disabled(group),
            }
        )

    return rows


# ==============================
# Run the group import
# ==============================
def import_groups(file_path):
    return post_file(
        f"{BASE_URL}/api/groups/import",
        {
            "ApiVersion": API_VERSION,
            "ApiKey": API_KEY,
            "Encoding": ENCODING,
            "ReplaceAllGroupMembers": True,
        },
        file_path,
    )


# ==============================
# Main process
# ==============================
def main():
    groups = read_csv(GROUPS_CSV)
    users = read_csv(USERS_CSV)
    memberships = read_csv(MEMBERSHIPS_CSV)

    existing_groups = get_existing_groups()
    rows = build_rows(groups, users, memberships, existing_groups)

    write_csv(
        GROUP_IMPORT_CSV,
        [
            "グループID",
            "グループ名",
            "説明",
            "メンバー種別",
            "メンバーキー",
            "メンバー名",
            "メンバーは管理者",
            "無効",
        ],
        rows,
    )

    print("CSV generated:", GROUP_IMPORT_CSV)

    if DRY_RUN:
        print("The import is not run because DRY_RUN=True")
        return

    result = import_groups(GROUP_IMPORT_CSV)
    print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()
Run
>python api_group_import.py
Execution Result
CSV generated: group_import\output\groups_import.csv
{
  "Id": 0,
  "StatusCode": 200,
  "Message": ": Group 0 added, 0 updated. Group members Added 3 and updated 0."
}
2. Read CSV files from an external system and create/update groups and their parent-child relationships

This sample registers groups and their parent-child relationships
with the Pleasanter Create Group API / Update Group API,
based on CSV files output from an external system.

Overview

It receives the organization information of an external system as CSV files,
and builds the group structure with the Pleasanter Create Group and Update Group APIs.

This sample works in two phases.

Phase Process
Phase1 Create / update the groups themselves and their members
Phase2 Update the parent-child relationships of the groups

The process flow is as follows.

  1. Read the input CSV files
  2. Get the existing groups from Pleasanter (/api/groups/get)
  3. Get the existing users from Pleasanter (/api/users/get)
  4. Phase1 - Decide whether to create or update based on the group name, and register the groups themselves and their members (/api/groups/create or /api/groups/{GroupId}/update)
  5. Get the existing groups from Pleasanter again (/api/groups/get)
  6. Phase2 - Update the groups again, including the parent-child relationships (/api/groups/{GroupId}/update)

Prerequisites

The users are already registered in Pleasanter
Group names are unique (used to decide whether to create or update)

Input Files

There are four input files.

input/
 ├ groups.csv
 ├ users.csv
 ├ user_group_memberships.csv
 └ group_relations.csv
groups.csv

Defines the group information.

Column name Description
group_code Group identification code
group_name Group name
is_active 1: Enabled / 0: Disabled
remark Description

Sample

group_code,group_name,is_active,remark
GRP_ADMIN,Administration Headquarters,1,Administration division
GRP_SALES,Sales Headquarters,1,Sales division
GRP_EAST,East Japan Sales Department,1,Sales in East Japan
users.csv

Defines the user information.

Column name Description
user_id User identification ID
login_id Pleasanter login ID
user_name User name
mail Mail
is_active 1: Enabled / 0: Disabled

Sample

user_id,login_id,user_name,mail,is_active
0001,yamada.taro,Taro Yamada,yamada@example.co.jp,1
0002,sato.hanako,Hanako Sato,sato@example.co.jp,1
user_group_memberships.csv

Defines the member information of the groups.

Column name Description
user_id User ID
group_code Group code
is_active 1: Enabled / 0: Disabled
is_group_admin 1: Group administrator / 0: Regular user

Sample

user_id,group_code,is_active,is_group_admin
0001,GRP_ADMIN,1,1
0002,GRP_SALES,1,0
group_relations.csv

Defines the parent-child relationships of the groups.

Column name Description
parent_group_code Parent group
child_group_code Child group
is_active 1: Included / 0: Excluded

Sample

parent_group_code,child_group_code,is_active
GRP_SALES,GRP_EAST,1
Python(api_group_upsert.py)
import csv
import json
from pathlib import Path

import requests

# ==============================
# Pleasanter connection settings
# ==============================
BASE_URL = "【URL】"
API_KEY = "【API key】"
API_VERSION = 1.1

# ==============================
# File settings (change them as appropriate for your environment)
# ==============================
INPUT_DIR = Path("./input")
GROUPS_CSV = INPUT_DIR / "groups.csv"
USERS_CSV = INPUT_DIR / "users.csv"
MEMBERSHIPS_CSV = INPUT_DIR / "user_group_memberships.csv"
RELATIONS_CSV = INPUT_DIR / "group_relations.csv"


# ==============================
# CSV input settings (change them as appropriate for your environment)
# ==============================
def read_csv(path):
    with open(path, "r", encoding="utf-8-sig", newline="") as f:
        return [
            {k.strip(): (v or "").strip() for k, v in row.items()}
            for row in csv.DictReader(f)
        ]


def is_active(row):
    return str(row.get("is_active", "1")).strip() == "1"


def to_bool_text(value):
    return "True" if str(value).strip() == "1" else "False"


# ==============================
# Pleasanter API operations
# ==============================
def post_json(url, payload):
    r = requests.post(
        url,
        json=payload,
        headers={"Content-Type": "application/json"},
        timeout=60,
    )
    r.raise_for_status()
    return r.json()


# ==============================
# Get groups
# ==============================
def get_groups():
    data = post_json(
        f"{BASE_URL}/api/groups/get",
        {"ApiVersion": API_VERSION, "ApiKey": API_KEY},
    )
    return {
        row["GroupName"]: row
        for row in data.get("Response", {}).get("Data", [])
        if row.get("GroupName")
    }


# ==============================
# Get users
# ==============================
def get_users():
    data = post_json(
        f"{BASE_URL}/api/users/get",
        {"ApiVersion": API_VERSION, "ApiKey": API_KEY},
    )
    return {
        row["LoginId"]: row
        for row in data.get("Response", {}).get("Data", [])
        if row.get("LoginId")
    }


# ==============================
# Create/update a group
# ==============================
def upsert_group(group_name, payload, existing_groups):
    current = existing_groups.get(group_name)

    if current:
        url = f"{BASE_URL}/api/groups/{current['GroupId']}/update"
        result = post_json(url, payload)
        print(f"[UPDATE] {group_name}")
    else:
        url = f"{BASE_URL}/api/groups/create"
        result = post_json(url, payload)
        print(f"[CREATE] {group_name}")

    return result


# ==============================
# Set the group members
# ==============================
def build_member_map(memberships):
    result = {}
    for row in memberships:
        if not is_active(row):
            continue
        group_code = row["group_code"]
        result.setdefault(group_code, []).append(row)
    return result


# ==============================
# Build the parent-child relationships
# ==============================
def build_relation_map(relations):
    result = {}
    for row in relations:
        if not is_active(row):
            continue
        parent_code = row["parent_group_code"]
        result.setdefault(parent_code, []).append(row["child_group_code"])
    return result


# ==============================
# Build the request payload for Phase1
# ==============================
def build_payload_phase1(group_row, member_rows, users_by_id, pleasanter_users):
    members = []

    for row in member_rows:
        user = users_by_id[row["user_id"]]
        login_id = user["login_id"]
        pleasanter_user = pleasanter_users[login_id]
        user_id = pleasanter_user["UserId"]
        is_admin = to_bool_text(row.get("is_group_admin", "0"))
        members.append(f"User,{user_id},{is_admin}")

    return {
        "ApiVersion": API_VERSION,
        "ApiKey": API_KEY,
        "GroupName": group_row["group_name"],
        "Body": group_row.get("remark", ""),
        "GroupMembers": members,
        "GroupChildren": [],
    }


# ==============================
# Build the request payload for Phase2
# ==============================
def build_payload_phase2(
    group_row,
    member_rows,
    child_codes,
    users_by_id,
    groups_by_code,
    pleasanter_users,
    existing_groups,
):
    members = []

    for row in member_rows:
        user = users_by_id[row["user_id"]]
        login_id = user["login_id"]
        pleasanter_user = pleasanter_users[login_id]
        user_id = pleasanter_user["UserId"]
        is_admin = to_bool_text(row.get("is_group_admin", "0"))
        members.append(f"User,{user_id},{is_admin}")

    children = []

    for child_code in child_codes:
        child_name = groups_by_code[child_code]["group_name"]
        child_group = existing_groups[child_name]
        children.append(f"Group,{child_group['GroupId']},")

    return {
        "ApiVersion": API_VERSION,
        "ApiKey": API_KEY,
        "GroupName": group_row["group_name"],
        "Body": group_row.get("remark", ""),
        "GroupMembers": members,
        "GroupChildren": children,
    }


# ==============================
# Main process
# ==============================
def main():
    groups = read_csv(GROUPS_CSV)
    users = read_csv(USERS_CSV)
    memberships = read_csv(MEMBERSHIPS_CSV)
    relations = read_csv(RELATIONS_CSV)

    groups_by_code = {row["group_code"]: row for row in groups}
    users_by_id = {row["user_id"]: row for row in users}
    members_by_group = build_member_map(memberships)
    children_by_parent = build_relation_map(relations)

    pleasanter_users = get_users()
    existing_groups = get_groups()

    # Phase 1: Create/update all groups (without child groups)
    print("=== Phase 1 ===")
    for group in groups:
        payload = build_payload_phase1(
            group,
            members_by_group.get(group["group_code"], []),
            users_by_id,
            pleasanter_users,
        )
        upsert_group(group["group_name"], payload, existing_groups)
        existing_groups = get_groups()

    # Phase 2: Update the parent-child relationships
    print("=== Phase 2 ===")
    existing_groups = get_groups()

    for group in groups:
        payload = build_payload_phase2(
            group,
            members_by_group.get(group["group_code"], []),
            children_by_parent.get(group["group_code"], []),
            users_by_id,
            groups_by_code,
            pleasanter_users,
            existing_groups,
        )
        upsert_group(group["group_name"], payload, existing_groups)


if __name__ == "__main__":
    main()
Run
>python api_group_upsert.py
Execution Result
=== Phase 1 ===
[CREATE] Administration Headquarters
[CREATE] Sales Headquarters
[CREATE] East Japan Sales Department
=== Phase 2 ===
[UPDATE] Administration Headquarters
[UPDATE] Sales Headquarters
[UPDATE] East Japan Sales Department

Confirmation Items in Case of Error

・Precautions when using the API and things to check if an error occurs
・FAQ: What to check if modified configuration files or API requests (JSON format) are not recognized correctly

Specification Changes

*API specifications have been partially changed since November 2018.**
- The URL format has been changed from '/pleasanter/api_items/xxxx' to '/pleasanter/api/items/xxxx'.
- The Content-Type specification has been changed from 'application/x-www-form-urlencoded' to 'application/json'.