はじめに
Backlog APIの仕様について調べていたところ、IDの取扱いやペイロード形式にハマりどころがあったので、備忘録としてまとめておきます。
基本的なエンドポイントからPythonでデータを取得する
以下のPythonコードを実行すると、基本的なエンドポイントからデータを取得できます。
.
├── data
│ └── output
│ └── ...json
├── .env
└── main.py
# %%
from dotenv import load_dotenv
import os
import requests
import json
import datetime
load_dotenv()
BACKLOG_API_KEY = os.getenv("BACKLOG_API_KEY")
BACKLOG_SPACE_KEY = os.getenv("BACKLOG_SPACE_KEY")
BASE_URL = f"https://{BACKLOG_SPACE_KEY}.backlog.com"
def fetch_api_data(path, method, data):
url = f"{BASE_URL}{path}"
print(url)
headers = {
"Content-Type": "application/json",
}
params = {"apiKey": BACKLOG_API_KEY}
res = requests.request(method, url, headers=headers, params=params, data=data)
print(res.status_code)
return res.json()
def save_response_data(path, method, json_data):
output_dir = "./data/output"
if method == "GET":
file_name = path.replace("/", "_") + ".json"
if method == "POST":
created = json_data.get("created", "")
file_name = path.replace("/", "_") + f"_post_{datetime.datetime.fromisoformat(created.replace('Z', '+00:00')).strftime('%Y%m%d_%H%M%S')}.json"
file_path = os.path.join(output_dir, file_name)
write_data = json.dumps(json_data, ensure_ascii=False, indent=4)
with open(file_path, "w", encoding="utf-8") as f:
f.write(write_data)
return write_data
def fetch_and_save(path, data=None):
if data is None:
method = "GET"
else:
method = "POST"
res = fetch_api_data(path, method, data)
save_response_data(path, method, res)
return res
# %%
# レート制限情報の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-rate-limit/
fetch_and_save("/api/v2/rateLimit")
# %%
# スペース情報の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-space/
fetch_and_save("/api/v2/space")
# %%
# プロジェクト一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-project-list/
fetch_and_save("/api/v2/projects")
with open("./data/output/_api_v2_projects.json", "r", encoding="utf-8") as f:
project_id = json.load(f)[0]["id"]
print(f"project_id: {project_id}")
# %%
# 優先度一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-priority-list/
fetch_and_save("/api/v2/priorities")
with open("./data/output/_api_v2_priorities.json", "r", encoding="utf-8") as f:
priorities = json.load(f)
for priority in priorities:
if priority["name"] == "中":
priority_id__medium = priority["id"]
print(f"priority_id__medium: {priority_id__medium}")
# %%
# 完了理由一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-resolution-list/
fetch_and_save("/api/v2/resolutions")
# %%
# 種別一覧の取得; developer.nulab.com/ja/docs/backlog/api/2/get-issue-type-list/
fetch_and_save(f"/api/v2/projects/{project_id}/issueTypes")
with open(f"./data/output/_api_v2_projects_{project_id}_issueTypes.json", "r", encoding="utf-8") as f:
issue_types = json.load(f)
for issue_type in issue_types:
if issue_type["name"] == "タスク":
issue_type_id__task = issue_type["id"]
print(f"issue_type_id__task: {issue_type_id__task}")
# %%
# カテゴリー一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-category-list/
fetch_and_save(f"/api/v2/projects/{project_id}/categories")
# %%
# プロジェクトユーザー一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-project-user-list/
fetch_and_save(f"/api/v2/projects/{project_id}/users")
with open(
f"./data/output/_api_v2_projects_{project_id}_users.json", "r", encoding="utf-8"
) as f:
user_id = json.load(f)[0]["id"]
print(f"user_id: {user_id}")
# %%
# プロジェクトの状態一覧の取得; https://developer.nulab.com/ja/docs/backlog/api/2/get-status-list-of-project/
fetch_and_save(f"/api/v2/projects/{project_id}/statuses")
ID系の取扱い
以下は、APIからデータを取得する以外で、IDがわからないものの確認方法です。
projectId
「プロジェクト設定」のメニューをクリックすると、https://<spaceKey>.backlog.com/EditProject.action?project.id=<projectId>というURLに遷移するので、そこで値が確認できます。
priorities
以下のようになっているので、これはおそらくどのプロジェクトでも共通と思われます。
- ID: 2 / 高
- ID: 3 / 中
- ID: 4 / 低
resolutions
以下のようになっているので、これもおそらくどのプロジェクトでも共通と思われます。
- ID: 0 / 対応済み
- ID: 1 / 対応しない
- ID: 2 / 無効
- ID: 3 / 重複
- ID: 4 / 再現しない
issueTypes
これはデフォルトで設定されている項目があるものの、優先度や完了理由と異なり可変のようです。https://<spaceKey>.backlog.com/ListIssueType.action?projectId=<projectId>で特定の種別をクリックすると、https://<spaceKey>.backlog.com/EditIssueType.action?issueType.id=<issueTypeId>&issueType.projectId=<projectId>というURLに遷移して値が確認できます。
userId
APIでユーザーの情報を取得すると、idとuserIdという2種類のIDが存在しています。個別ユーザーのアクティビティ画面ではURLはuserIdの方が利用されています。
https://<spaceKey>.backlog.com/user/<userId>#activity
ただし、後述している課題の担当者については、idの方が利用されていました。ややこしいですね・・・。
Statuses
以下のようになっているので、これもおそらくどのプロジェクトでも共通と思われます。
- ID: 1 / 未対応
- ID: 2 / 処理中
- ID: 3 / 処理済み
- ID: 4 / 完了
課題を作成する
上のコードに合わせて、以下のコードで課題を追加できます。
# %%
# 課題の追加; https://developer.nulab.com/ja/docs/backlog/api/2/add-issue/
data = {
"projectId": project_id,
"summary": "TEST",
"description": "This is a test issue created via Backlog API.",
"issueTypeId": issue_type_id__task,
"priorityId": priority_id__medium,
"assigneeId": user_id,
}
fetch_and_save("/api/v2/issues", data=json.dumps(data))
なお、APIドキュメントではリクエストパラメータがContent-Type:application/x-www-form-urlencodedと記載されていますが、application/jsonでも正常にリクエストを送ることができました。(他のエンドポイントは調べていません)
おわりに
ということで、ID系の取扱いが分かりにくかったのと、Content-Typeがドキュメントと違っても利用できたので、備忘録として残しておきます。
余談ですが、『先輩データサイエンティストからの指南書』を読んでPython Interactive Windowの存在を初めて知って使ってみましたが、これめちゃくちゃ便利ですね・・・!

