Backlog APIで添付ファイル付きの課題を追加する

こんにちは。Kaneyasuです。

今日はBacklogのお話です。
Backlog APIで添付ファイル付きの課題を登録する方法を紹介します。

Backlog APIは無論公式ドキュメントがありますが、APIという文化に慣れていないと読み取りきれないこともあると思います。
私もそんな一人で、APIを使って課題は追加できるだけれど、添付ファイルの付け方がわからず少々戸惑いました。
解決したので、書き記しておけば誰かの役に立つかなと思った次第です。

https://developer.nulab.com/ja/docs/backlog/

[Backlog ヘルプセンター - Backlog API で課題を登録する](https://support-ja.backlog.com/hc/ja/articles/360046783973-Backlog-API-%E3%81%A7%E8%AA%B2%E9%A1%8C%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B)


# 本記事のターゲット

Backlogを運用していて、APIを使ってより効率的に使いたい方。

本記事は、BackAPIのv2を元に記載しています。
サンプルコードはPython 3.11.4で書いています。

# 事前準備

Backlog APIは、各種言語からHTTPのリクエストを送って利用します。
プログラムを書く前の準備として、以下のものが必要になります。

- 自身が契約しているBacklogのURL
- APIキー
- プロジェクトID
- 課題の種別のID

## APIキーの取得方法

Backlog APIは認証が必要で、APIキーによる認証とOAuthによる認証がありますが、APIキーの方が手軽だと思います。

APIキーの取得方法は、公式ドキュメントにあります。

[Backlog ヘルプセンター - APIの設定](https://support-ja.backlog.com/hc/ja/articles/360035641754-API%E3%81%AE%E8%A8%AD%E5%AE%9A)

## プロジェクトIDの取得方法

APIで課題を追加する際、どのプロジェクトに追加するかをIDで指定する必要があります。
プロジェクトのIDは、「プロジェクト設定」を開いた時のURLで見ることができます。

プロジェクト設定画面を開いた時、ブラウザのURLに、このような形でプロジェクトIDが確認できるはずです。

```
https://{ユーザー固有の文字列}.backlog.jp/ViewPermission.action?projectId={プロジェクトID}
```

## 課題の種別のIDの取得方法

APIで課題を追加する際、タスク・バグをどの種別で追加するか、IDで指定する必要があります。
これは、プロジェクト設定画面の「種別」で種別の名称をクリックすると確認できます。

種別の件名をクリックした時、ブラウザのURLに、このような形で種別のIDが確認できるはずです。


```
https://{ユーザー固有の文字列}.backlog.jp/EditIssueType.action?issueType.id={課題の種別のID}&issueType.projectId={プロジェクトID}

```

　# 添付ファイル付きの課題を登録する

 添付ファイル付きの課題を登録する流れは、一言で言うと以下の通りです。

 - 添付ファイルを送信して、添付ファイルのIDを控える
 - 添付ファイルのIDを指定しながら、課題を追加する

これで課題の追加と添付ファイルの登録が一気にできます。
このような流れになるのは、添付ファイルの送信と、課題の追加が別のAPIになっているからです。
よくよく考えれば当たり前なのですが、APIの文化に慣れてないと戸惑いますね。

https://developer.nulab.com/ja/docs/backlog/api/2/post-attachment-file/#

https://developer.nulab.com/ja/docs/backlog/api/2/add-issue/#

ちなみに、既存の課題に添付ファイルを追加する場合は、課題の更新で添付ファイルのIDを指定すれば大丈夫です。

https://developer.nulab.com/ja/docs/backlog/api/2/update-issue/#

# サンプルコード

特定のディレクトリに送信する添付ファイル群を置いて、それらを全部課題に登録するとします。

```python
import os 
import http
import requests
from requests import Response

base_url = "自身が契約しているBacklogのURL/api/v2"
dir_path = "添付ファイル群のあるディレクトリパス"

# 添付ファイルの送信
attachments: list = []
for file in os.listdir(dir_path):
    attachment_file_path: str = os.path.join(dir_path, file)
    res: Response = requests.post(
        f"{base_url}/space/attachment",
        params={"apiKey": "APIキー"},
        files={"file": (file, open(attachment_file_path, "rb"))},
        timeout=(3.0, 7.5),
    )
    if res.status_code not in [http.HTTPStatus.OK, http.HTTPStatus.CREATED]:
        raise Exception(f"Failed to upload attachment: {res.text}")
    attachments.append(res.json().get("id"))

# 課題の追加
res: Response = requests.post(
    f"{base_url}/issues",
    params={"apiKey": "APIキー"},
    data={
        "projectId": "プロジェクトID",
        "summary": "課題のタイトル",
        "description": "課題の本文",
        "issueTypeId": "課題の種別のID",
        "priorityId": "3",
        "dueDate": "2023-12-31",
        "attachmentId[]": attachments,
    },
    timeout=(3.0, 15.0),
)

if res.status_code not in [http.HTTPStatus.OK, http.HTTPStatus.CREATED]:
    raise Exception(f"Failed to create issue: {res.text}")
     
```

# 最後に

本記事がどなたかのお役に立てば幸いです。