開発者向け機能:API:グループ操作:グループ取得
## 概要
APIを使用してグループのレコードを取得する事ができます。
## 事前準備
APIの操作を行う前に[APIキーの作成](/manual/api-key)を実施してください。
## リクエスト
下記のリクエスト形式で、jsonデータを送信します。
|設定項目|値|
|:--|:--|
|HTTPメソッド|POST|
|Content-Type |application/json|
|文字コード|UTF-8|
|URL|http://{サーバー名}/api/groups/get (※1)|
|Body|以下のjsonデータを参考のこと|
(※1){サーバー名}の部分は、適宜、環境に合わせて編集してください。
pleasanter.netの場合は以下の形式になります。
https\://pleasanter.net/fs/api/groups/get
##### JSON
```
{
"ApiVersion": 1.1,
"ApiKey": "sad610bHDo04720DoloA356...",
"View": {
"ColumnFilterHash": {
"GroupId": "[11,12]"
}
}
}
```
GroupIdによるフィルタは、複数の値を指定可能な配列となっておりますので上記のように記述してください。
## レスポンス
下記の形式のjsonデータが選択したGroupIdの数だけ返却されます。 データのレイアウトは[こちら](/manual/api-group)を参照してください。
##### JSON
```
{
"StatusCode": 200,
"Response": {
"Offset": 0,
"PageSize": 200,
"TotalCount": 2,
"Data": [
{
"TenantId": 1,
"GroupId": 11,
"Ver": 1,
"GroupName": "グループ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": {
}
}
]
}
}
```
## サンプルコード
##### コード内の【 ... 】 は適宜修正してください。
<details>
<summary>1. 外部連携されたCSVを読み込みグループをインポートする</summary>
本サンプルは、外部システムから出力されたCSVをもとに
インポート用CSVを生成し、APIでインポートするサンプルです。
#### 概要
外部システムのユーザ・組織情報をCSV形式で受け取り、
PleasanterのグループインポートAPIを利用してグループを作成または更新します。
処理の流れは次の通りです。
1. 入力CSVを読み込む
2. Pleasanterから既存グループを取得(/api/groups/get)
3. グループ名で既存グループを判定
4. グループインポート用CSVを生成
5. グループインポートAPIを実行(/api/groups/import)
#### 前提
ユーザは事前にPleasanterへ登録済み
グループ名は一意である(作成/更新の判定に使用)
#### 入力ファイル
外部から連動想定の入力ファイルは3つです。
```
input/
├ groups.csv
├ users.csv
└ user_group_memberships.csv
```
##### groups.csv
グループ情報を定義するCSVです。
| 列名 | 説明 |
| ---------- | ----------- |
| group_code | グループ識別コード |
| group_name | グループ名 |
| is_active | 1:有効 / 0:無効 |
| remark | 説明 |
サンプル
```
group_code,group_name,is_active,remark
GRP_ADMIN,管理本部,1,管理部門
GRP_SALES,営業本部,1,営業部門
```
##### users.csv
ユーザ情報を定義するCSVです。
| 列名 | 説明 |
| --------- | ---------------- |
| user_id | ユーザ識別ID |
| login_id | PleasanterログインID |
| user_name | ユーザ名 |
| mail | メールアドレス |
| is_active | 1:有効 / 0:無効 |
サンプル
```
user_id,login_id,user_name,mail,is_active
0001,yamada.taro,山田 太郎,yamada@example.co.jp,1
0002,sato.hanako,佐藤 花子,sato@example.co.jp,1
```
##### user_group_memberships.csv
ユーザとグループの所属関係を定義するCSVです。
| 列名 | 説明 |
| ---------- | ----------- |
| user_id | ユーザID |
| group_code | グループコード |
| is_active | 1:有効 / 0:無効 |
|is_group_admin| 1:グループの管理者 / 0:通常メンバー|
サンプル
```
user_id,group_code,is_active,is_group_admin
0001,GRP_ADMIN,1,1
0002,GRP_ADMIN,1,0
```
#### 出力ファイル
生成されるCSVは以下です。
```
output/
└ groups_import.csv
```
CSVのフォーマットについては、[グループインポート](https://pleasanter-cms-1112983746-staging.azurewebsites.net/ja/manual/group-import)の仕様に従います。
##### Python(api_group_import.py)
```
import csv
import json
from pathlib import Path
import requests
# ==============================
# Pleasanter 接続設定
# ==============================
BASE_URL = "【URL】"
API_KEY = "【APIキー】"
API_VERSION = 1.1
ENCODING = "UTF-8"
# True : CSV生成のみ
# False: CSV生成後インポート実行
DRY_RUN = True
# ==============================
# ファイル設定(環境にあわせ適宜変更してください)
# ==============================
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入出力設定(環境にあわせ適宜変更してください)
# ==============================
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操作
# ==============================
def post_json(url, payload):
r = requests.post(
url,
json=payload,
headers={"Content-Type": "application/json"},
)
r.raise_for_status()
return r.json()
# ==============================
# ファイルアップロード操作
# ==============================
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()
# ==============================
# グループ登録済か確認するための辞書を作成
# ==============================
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
# ==============================
# CSV用の行データを作成
# ==============================
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 = []
# グループ本体行
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),
}
)
# メンバー行
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
# ==============================
# グループインポート実行
# ==============================
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,
)
# ==============================
# メイン処理
# ==============================
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生成:", GROUP_IMPORT_CSV)
if DRY_RUN:
print("DRY_RUN=True のためインポートは実行しません")
return
result = import_groups(GROUP_IMPORT_CSV)
print(json.dumps(result, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()
```
##### 実行
```
>python api_group_import.py
```
##### 実行結果
```
CSV生成: group_import\output\groups_import.csv
{
"Id": 0,
"StatusCode": 200,
"Message": ": グループ 0 件追加、0 件更新しました。グループメンバー 3 件追加、0 件更新しました。"
}
```
</details>
<details>
<summary>2. 外部連携されたCSVを読み込みグループおよび親子関係を作成/更新する</summary>
本サンプルは、外部システムから出力されたCSVをもとに
Pleasanterのグループ作成API / グループ更新APIを利用して
グループおよび親子関係を登録するサンプルです。
#### 概要
外部システムの組織情報をCSVで受け取り、
Pleasanterのグループ作成・更新APIを利用してグループ構造を作成します。
本サンプルでは **2フェーズ処理** で実現しています。
| フェーズ | 処理内容 |
| ------ | ------------------- |
| Phase1 | グループ本体とメンバーを作成 / 更新 |
| Phase2 | グループ親子関係を更新 |
処理の流れは次の通りです。
1. 入力CSVを読み込む
2. Pleasanterから既存グループを取得する(/api/groups/get)
3. Pleasanterから既存ユーザを取得する(/api/users/get)
4. Phase1-グループ名をもとに create / update を判定し、グループ本体とメンバーを登録する(/api/groups/create または /api/groups/{GroupId}/update)
5. Pleasanterから既存グループを再取得する(/api/groups/get)
6. Phase2-親子関係を含めてグループを再更新する(/api/groups/{GroupId}/update)
#### 前提
ユーザは事前にPleasanterへ登録済み
グループ名は一意である(作成/更新の判定に使用)
#### 入力ファイル
入力ファイルは4つです。
```
input/
├ groups.csv
├ users.csv
├ user_group_memberships.csv
└ group_relations.csv
```
##### groups.csv
グループ情報を定義します。
| 列名 | 説明 |
| ---------- | ----------- |
| group_code | グループ識別コード |
| group_name | グループ名 |
| is_active | 1:有効 / 0:無効 |
| remark | 説明 |
サンプル
```
group_code,group_name,is_active,remark
GRP_ADMIN,管理本部,1,管理部門
GRP_SALES,営業本部,1,営業部門
GRP_EAST,東日本営業部,1,営業東日本
```
##### users.csv
ユーザ情報を定義します。
| 列名 | 説明 |
| --------- | ---------------- |
| user_id | ユーザ識別ID |
| login_id | PleasanterログインID |
| user_name | ユーザ名 |
| mail | メール |
| is_active | 1:有効 / 0:無効 |
サンプル
```
user_id,login_id,user_name,mail,is_active
0001,yamada.taro,山田 太郎,yamada@example.co.jp,1
0002,sato.hanako,佐藤 花子,sato@example.co.jp,1
```
##### user_group_memberships.csv
グループのメンバー情報を定義します。
| 列名 | 説明 |
| -------------- | --------- |
| user_id | ユーザID |
| group_code | グループコード |
| is_active | 1:有効 / 0:無効 |
| is_group_admin | 1:グループ管理者 / 0:通常ユーザ |
サンプル
```
user_id,group_code,is_active,is_group_admin
0001,GRP_ADMIN,1,1
0002,GRP_SALES,1,0
```
##### group_relations.csv
グループの親子関係を定義します。
| 列名 | 説明 |
| ----------------- | ----- |
| parent_group_code | 親グループ |
| child_group_code | 子グループ |
| is_active | 1:対象 / 0:対象外 |
サンプル
```
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 接続設定
# ==============================
BASE_URL = "【URL】"
API_KEY = "【APIキー】"
API_VERSION = 1.1
# ==============================
# ファイル設定(環境にあわせ適宜変更してください)
# ==============================
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入力設定(環境にあわせ適宜変更してください)
# ==============================
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操作
# ==============================
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()
# ==============================
# グループ取得
# ==============================
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")
}
# ==============================
# ユーザー取得
# ==============================
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")
}
# ==============================
# グループの作成/更新
# ==============================
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
# ==============================
# グループメンバーの設定
# ==============================
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
# ==============================
# 親子関係の構築
# ==============================
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
# ==============================
# 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": [],
}
# ==============================
# 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,
}
# ==============================
# メイン処理
# ==============================
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: 全グループを作成/更新(子グループなし)
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: 親子関係を更新
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()
```
##### 実行
```
>python api_group_upsert.py
```
##### 実行結果
```
=== Phase 1 ===
[CREATE] 管理本部
[CREATE] 営業本部
[CREATE] 東日本営業部
=== Phase 2 ===
[UPDATE] 管理本部
[UPDATE] 営業本部
[UPDATE] 東日本営業部
```
</details>
## エラー時の確認事項
[・API使用時の注意点やエラーが発生する場合の確認事項](/manual/faq-api)
[・FAQ:変更後の設定ファイルやAPIリクエスト(JSON形式)が正しく認識されない場合の確認事項](/manual/faq-json-format)
## 仕様変更について
**※ 2018年11月よりAPIの仕様が一部変更となりました。**
- URLの形式が '/pleasanter/api_items/xxxx' から '/pleasanter/api/items/xxxx' に変更されました。
- Content-Type の指定が'application/x-www-form-urlencoded' から 'application/json'に変更されました。



