JiraのラベルをREST APIで事前GETなしに追加・削除する

JiraのラベルをREST APIで事前GETなしに追加・削除する

Jira APIでラベルを追加・削除するとき、従来のread-modify-writeパターンは非効率で競合の原因になります。Edit issue APIの`update`操作を使えば、事前GETなしの1リクエストで安全にラベル操作ができるので、その方法を検証結果とともに紹介します。
2026.08.31

どうも!オペ部の西村祐二です!

JiraのラベルをAPIから付け外しするとき、fields.labelsへの指定は配列の丸ごと置換になります。そのため「GETで現在のラベルを取得 → 手元でマージ → PUTで書き戻す」という手順を踏みがちです。この方式ではリクエスト数が増えるうえ、GETとPUTの間に他の更新が入ると、その変更を上書きしてしまいます。実際、筆者の手元のアプリケーションでもこの方式で、課題1件あたりGET 2回 + PUT 3回を発行していました。

Edit issue APIupdate操作を使うと、事前GETなしの1リクエストでラベルの追加・削除だけをサーバ側に反映できたので、検証結果と合わせて紹介します。

今回やること

この記事で分かること:

  • update.labelsのadd / removeで、事前GETなしにラベルを追加・削除する方法
  • fieldsupdateの違いと使い分け
  • 他フィールド(期日など)を同一リクエストで組み合わせる方法

fieldsとupdateの違い

Edit issue(PUT /rest/api/3/issue/{issueIdOrKey})のリクエストボディでは、フィールドの編集をfieldsupdateの2通りで指定できます。

  • fields: 値をそのまま設定する単純な方式。配列フィールドは送った配列で丸ごと置換される
  • update: set / add / remove / edit / copyという操作(verb)を指定する方式。配列フィールドへの要素の追加・削除を操作として表現できる

update.labelsなら「このラベルを足す」「このラベルを消す」という操作だけを送るので、現在値を知らなくても他のラベルに影響しません。値を丸ごと設定するならfields、配列の部分更新ならupdateという使い分けになります。

なお、公式リファレンスには同じフィールドをfieldsupdateの両方に含められないことが明記されています("Fields included in here cannot be included in update.")。

試してみる

検証環境

  • Jira Cloud(REST API v3)
  • macOS + curl
  • 認証: AtlassianアカウントのAPIトークンを使ったBasic認証。メールアドレスとAPIトークンを環境変数JIRA_EMAIL / JIRA_API_TOKENにセットしておきます
  • 検証日: 2026-08-31

検証に使った課題には、あらかじめ4つのラベルが付いています。

curl -s -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  "https://your-domain.atlassian.net/rest/api/3/issue/ISSUE-1?fields=labels" | jq -c '.fields.labels'
["existing-a","existing-b","existing-c","existing-d"]

1. ラベルを追加する

update.labelsaddを1つ入れてPUTします。

curl -s -o /dev/null -w "%{http_code}\n" \
  -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  -X PUT -H "Content-Type: application/json" \
  "https://your-domain.atlassian.net/rest/api/3/issue/ISSUE-1" \
  -d '{"update":{"labels":[{"add":"new-label"}]}}'

結果は204(No Content)でした。GETでラベルを確認すると、既存の4ラベルはそのままで、指定したラベルだけが追加されています。

["existing-a","existing-b","existing-c","existing-d","new-label"]

2. 追加と削除を1リクエストで行う

「古いラベルを外して新しいラベルを付ける」という付け替えも、addとremoveを並べれば1リクエストで済みます。

curl -s -o /dev/null -w "%{http_code}\n" \
  -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  -X PUT -H "Content-Type: application/json" \
  "https://your-domain.atlassian.net/rest/api/3/issue/ISSUE-1" \
  -d '{"update":{"labels":[{"add":"replacement-label"},{"remove":"new-label"}]}}'

結果は204で、GETで確認すると両方の操作が反映されていました。

["existing-a","existing-b","existing-c","existing-d","replacement-label"]

3. 別フィールドと同時に更新する

fieldsupdateは、同じフィールドを指定しない限り1つのリクエストに同居できます。ラベルの追加と期日の設定を同時に行ってみます。

curl -s -o /dev/null -w "%{http_code}\n" \
  -u "$JIRA_EMAIL:$JIRA_API_TOKEN" \
  -X PUT -H "Content-Type: application/json" \
  "https://your-domain.atlassian.net/rest/api/3/issue/ISSUE-1" \
  -d '{"update":{"labels":[{"add":"another-label"}]},"fields":{"duedate":"2026-09-30"}}'

結果は204で、GETで確認するとラベルの追加とduedateの設定が1回のPUTで反映されていました。

{"labels":["existing-a","existing-b","existing-c","existing-d","replacement-label","another-label"],"duedate":"2026-09-30"}

挙動のポイント

  1. 同じフィールドを両方に書くと400になる
    • 公式リファレンスの記載どおり、fields.labelsupdate.labelsを同時に送ると、Field 'labels' cannot appear in both 'fields' and 'update'というエラーメッセージとともに400が返りました
  2. 存在しないラベルのremoveはエラーにならない
    • 付いていないラベルをremoveしても204が返り、他のラベルにも影響しませんでした。同じリクエストを繰り返しても結果が変わらないので、リトライしやすい挙動です
  3. 更新後の状態はreturnIssue=trueで受け取れる
    • 成功時のレスポンスはデフォルトでは204でボディが返りませんが、クエリパラメータreturnIssue=trueを付けると200で更新後の課題が返ることも確認しました。反映確認のためのGETも省けます

まとめ

GET → マージ → PUTのread-modify-writeをupdate.labelsのadd / removeに置き換えると、リクエスト数が減り、並行更新との競合も避けられます。冒頭で触れた手元のアプリケーションも、この置き換えで課題1件あたりPUT 1回に削減できました。

ラベル以外の配列フィールドにも同様の操作が定義されているので、部分更新をしたい場面ではまずupdateが使えないか確認するのが良さそうです。

誰かの参考になれば幸いです。


参考リンク:

この記事をシェアする

関連記事