課題 API リファレンス

課題(issue)の作成・更新・一覧、カンバンボード、コメント、課題設定(種別・状態・カテゴリ)、添付、保存済みフィルタ、マイ課題、プロフィールの API です。CI や AI エージェントから課題を操作する用途を想定しています。

ℹ️

認証・エラー形式・ページング・ロールと権限は REST API リファレンスの共通仕様 を参照してください。このページの auth 列は共通仕様の「ロールと権限」の行に対応します(読む = 全ロール、書く = owner / admin / member、admin = owner / admin)。

人物オブジェクトの email は owner / admin または本人にのみ返します。外部メンバーには、管理権限があっても本人以外の email を返しません。招待の email は内部の owner / admin のみ取得できます。name は常に文字列で、表示名が未設定の場合はメールのローカル部先頭 2 文字 + *** です。 以下の人物レスポンス例は、本人以外を member / viewer として取得した場合です。

前提

  • project で課題機能が有効で、project key(例: NOLTO)が設定されていること。無効な project への呼び出しは 404 です。
  • 課題はキー NOLTO-12 で表示されますが、API のパスは番号 12 を使います(/issues/12)。
  • {projectId} は project の UUID です。

課題

GET/api/projects/{projectId}/issues読む

project の課題を絞り込み、50 件ずつ返します。不正な query 値は無視して既定値を使います。

query値
status状態 UUID。繰り返しまたはカンマ区切りで複数指定できます
closedexclude(既定)/ include / only
assigneemember UUID / me / none。複数指定可
type種別 UUID。複数指定可
priorityhigh / normal / low。複数指定可
categoryカテゴリ UUID。複数指定可。選択したいずれかのカテゴリを持つ課題
parent親の課題番号(その子課題)/ none(親なし)
updated7d:直近7日以内に更新された課題
overdue1 / true:期限日が DB の当日より前で、状態が未完了の課題
q件名・本文の部分一致(100文字まで)。NOLTO-12 は番号一致、1〜9桁の数字 12 は番号一致または件名・本文の部分一致
sortupdated(既定)/ due / priority / number / created / assignee(担当者の表示名。表示名がなければメールアドレス、担当未設定は末尾)/ status(状態の並び順)/ type(種別の並び順)/ subject(件名)/ category(先頭カテゴリの並び順。カテゴリなしは末尾)
orderasc / desc。既定は due / assignee / status / type / subject のとき asc、それ以外は desc
page1 始まり。不正値は 1

status / type / priority / assignee / category は繰り返しとカンマ区切りを併用できます。各項目内は OR、異なる項目間は AND です。不正値を除き、重複を取り除いた先頭20件を使います。単一値の既存 URL・CLI も利用できます。status を明示した場合は従来どおり closed より優先します。指定がなければ closed=exclude です。

同値の課題は常に番号の降順で並びます。

{
  "issues": [
    {
      "id": "0aa00000-0000-4000-8000-000000000012",
      "number": 12,
      "key": "NOLTO-12",
      "subject": "ログイン画面の文言",
      "priority": "normal",
      "type": { "id": "uuid", "name": "タスク", "color": "#2563eb" },
      "status": { "id": "uuid", "name": "処理中", "color": "#ca8a04", "isClosed": false },
      "assignee": { "id": "uuid", "email": null, "name": "山田" },
      "createdBy": { "id": "uuid", "email": null, "name": "pm***" },
      "categories": [],
      "dueDate": "2026-09-01",
      "closedAt": null,
      "createdAt": "2026-08-29T01:23:45.678Z",
      "updatedAt": "2026-08-29T02:00:00.000Z",
      "commentCount": 2,
      "parent": null,
      "childCount": 0
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 50
}
status意味
200課題一覧
404project が見つからない、または課題機能が無効

ビューと絞り込み候補の件数

GET/api/projects/{projectId}/issues/facets読む

一覧と同じ query を受け取り、結果の総数と各ビュー・絞り込み候補の件数を返します。page / sort / order は件数に影響しません。課題機能と issues スコープが必要です。

{
  "total": 8,
  "views": { "open": 12, "mine": 8, "todo": 16, "week": 27, "all": 28, "overdue": 2, "nobody": 3, "priority:high": 4, "type:<uuid>": 11, "filter:<uuid>": 5 },
  "facets": {
    "status": { "<uuid>": 8 },
    "type": { "<uuid>": 7 },
    "assignee": { "<uuid>": 8, "none": 0 },
    "priority": { "high": 0, "normal": 3, "low": 5 },
    "category": { "<uuid>": 5 },
    "flags": { "mine": 8, "open": 8, "updatedWithin": 3, "overdue": 0, "topLevel": 8 }
  }
}

views は現在の絞り込みと独立した件数です。open は担当を問わない未完了の全件、mine は自分の未完了、todo は sortOrder が最小の未完了状態、week は完了を含む直近7日の更新、all は完了を含む全件です。overdue / nobody / priority:high / type:<uuid> は、それぞれ未完了の期限切れ・担当なし・高優先度・指定種別を数えます。未完了状態がなければ todo キーを省略します。保存フィルタは自分のものと他人の共有分だけを数え、正規化できない行は省きます。

facets の各グループは、そのグループ自身の選択だけを外して数えます。状態・種別・カテゴリの全設定と担当可能メンバーの UUID、担当なしの none を含み、該当がなければ 0 を返します。カテゴリが複数ある課題は各カテゴリに1件ずつ数えます。

flags は現在の条件にフラグを設定した件数です。mine は担当者の OR 条件に me を加え、open は未完了に限定、updatedWithin は直近7日、overdue は期限切れ、topLevel は親なしに設定します。ボードから呼んでも、ビュー件数と集計には状態・closed 条件を適用します。

status意味
200総数・ビュー件数・絞り込み候補件数
401未認証
403project の読み取り権限または issues スコープがない
404project が見つからない、または課題機能が無効
POST/api/projects/{projectId}/issues書く

課題を作成します。種別と状態を省略すると project の既定値を使います。

{
  "subject": "ログイン画面の文言",
  "body": "## 背景\n\n表示を更新します。",
  "priority": "normal",
  "assigneeId": "member-uuid",
  "dueDate": "2026-09-01",
  "categoryIds": ["category-uuid"],
  "parentId": null,
  "attachmentIds": []
}
field条件
subject必須、1〜255 文字
body任意、100,000 文字まで
typeId / statusId種別 / 状態 UUID。省略時は既定値
priorityhigh / normal / low。既定は normal
assigneeIdmember UUID または null。member 以外は 400
dueDateYYYY-MM-DD または null
categoryIdsカテゴリ UUID、20 件まで
parentId親課題 UUID または null
attachmentIds添付 UUID、20 件まで
{
  "issue": {
    "id": "0aa00000-0000-4000-8000-000000000012",
    "number": 12,
    "key": "NOLTO-12",
    "subject": "ログイン画面の文言",
    "body": "## 背景\n\n表示を更新します。"
  }
}
status意味
201作成した IssueDetail
400入力、member、マスタ、親課題、添付が不正
402Free の project ごとの課題数上限(100 件)を超過
GET/api/projects/{projectId}/issues/{number}読む

課題の詳細、コメント、本文の添付、子課題をまとめて返します。number は project 内の課題番号です。watching は認証ユーザー自身のウォッチ状態です。

{
  "issue": { "id": "uuid", "number": 12, "key": "NOLTO-12", "subject": "ログイン画面の文言", "body": "Markdown", "reactions": [] },
  "comments": [],
  "attachments": [],
  "children": [],
  "watching": true,
  "watcherCount": 2,
  "watchers": [{ "id": "user-uuid", "email": null, "name": "山田 花子" }]
}

watchers は現メンバーのウォッチャーを、ウォッチした順で返します。

status意味
200詳細と関連データ
400課題番号が不正
404課題が見つからない

issue.reactions と各 comments[].reactions は、対象に付いたリアクションを固定セット順で返します。

PATCH/api/projects/{projectId}/issues/{number}書く

課題を更新します。作成時のフィールドを 1 つ以上指定し、任意で変更履歴と同じ行に残すコメントを付けられます。

{
  "statusId": "status-uuid",
  "comment": "対応しました"
}

attachmentIds は comment があればコメントに、無ければ本文に紐付きます。変更とコメントの両方が無い場合、レスポンスの comment は null です。

{
  "issue": { "id": "uuid", "number": 12, "key": "NOLTO-12", "status": { "id": "status-uuid", "name": "完了", "color": "#16a34a", "isClosed": true } },
  "comment": { "id": "comment-uuid", "body": "対応しました", "changes": [{ "field": "status", "from": "old-uuid", "to": "status-uuid", "fromLabel": "処理中", "toLabel": "完了" }] }
}
status意味
200更新した課題と履歴 / コメント行
400入力不正。親が別 project、親自身が子、自分自身、または子を持つ課題への親設定は parent_invalid
404課題が見つからない

任意の expectedUpdatedAt に ISO 8601 の日時を指定すると、行をロックして現在の更新日時とミリ秒精度で比較します。GET の issue.updatedAt は new Date(value).toISOString() で正規化して送れます。一致しない場合は変更せず、409 と { error: "issue_stale", message: "課題が他の人に更新されました。", updatedAt } を返します。省略時は従来どおり更新します。

POST/api/projects/{projectId}/issues/{number}/checklist書く

本文のチェックリストを1行だけ変更します。本文全体の上書きは行いません。

{ "line": 0, "checked": true, "expected": "- [ ] 動作を確認する" }

line は body.split("\n") の0始まりの整数、checked は変更後の状態、expected は読み取った行そのもの(2,000文字以内)です。CRLF の本文では行末の \r も含めます。余分なフィールドは受け付けません。

- / * / + と番号付きリストのタスクを扱い、バッククォート・チルダのコードフェンス内は対象外です。行ロック中に期待値を比較し、チェック記号だけを変更して改行を維持します。更新日時は進みますが、コメントの変更履歴・活動記録・通知は追加しません。

status意味
200課題 GET と同じ詳細レスポンス
400入力不正
403編集権限または issues:write スコープがない
409行が不一致・範囲外・タスクでない場合は { error: "issue_body_stale", message, body }。body は最新本文。アーカイブ済みプロジェクトは project_archived
410課題はゴミ箱内
DELETE/api/projects/{projectId}/issues/{number}admin

課題をゴミ箱へ移動します。30 日間保持され、owner / admin が復元できます。子課題の親は未設定になり、添付・コメント・関連は保持されます。

status意味
204削除済み
403owner / admin ではない
404課題が見つからない

ゴミ箱・復元・完全削除

削除済み課題の GET / PATCH / DELETE と、コメント(編集・削除・版一覧・リアクションを含む)、watch / watchers、reactions、links、backlinks は 410 を返します。件名・本文は含みません。

{ "error": "issue_deleted", "message": "この課題は削除されました。", "deletedAt": "2026-09-05T00:00:00.000Z", "deletedBy": { "id": "user-uuid", "name": "表示名" } }

削除者のプロフィールが削除されている場合、deletedBy は null です。

POST/api/projects/{projectId}/issues/{number}/restoreadmin

owner / admin が復元します。子課題の親は再接続しません。Free の課題件数上限を再検査します。

status意味
200復元した課題を issue に返す
402プランの課題件数上限
403復元権限なし
404課題が存在しない
409issue_not_deleted(削除されていない)
DELETE/api/projects/{projectId}/issues/{number}/purgeowner

ゴミ箱内の課題を完全に削除します。コメント・履歴・関連も削除し、添付を自動 GC の対象にします。この操作は取り消せません。

status意味
204完全削除済み
403owner ではない
404課題が存在しない
409issue_not_deleted(削除されていない)
GET/api/projects/{projectId}/issues/trash?page=1admin

owner / admin 向けのゴミ箱一覧です。削除日時降順、1 ページ 50 件。page は 1 以上の整数で、不正値は 400、権限なしは 403 です。

200 の応答は { issues, total, page, pageSize }。各行は id, number, key, subject, deletedAt, deletedBy, purgeAt を持ちます。purgeAt は削除日時の 30 日後です。末尾を超えるページは空配列と総件数を返します。

30 日を過ぎた課題は daily ジョブが完全に削除します。復元しても updated_at は変更されません。

親子課題

親子は 1 階層のみです。parentId には同じ project にある、親を持たない課題を指定します。子を持つ課題には親を設定できません。一覧では parent=12 で 12 番の子課題、parent=none で親を持たない課題を取得できます。

ロードマップ上の位置

詳細 GET は roadmap スコープを持つ閲覧者にだけ roadmapPositions 配列を返します。スコープがなければキー自体を省略し、スコープがあって未リンクなら空配列です。リンクは Git の task.issues を同期して設定します。

{
  "roadmapPositions": [{
    "slug": "main", "roadmapName": "開発計画",
    "phaseId": "p1", "phaseNo": "01", "phaseTitle": "実装",
    "taskId": "t1", "taskNo": "01.1", "taskTitle": "課題リンク",
    "taskStatus": "in-progress"
  }]
}

該当 task は /projects/{projectId}/roadmaps/{slug}?ph={taskId} で開けます。

関連コミット / PR

詳細 GET は git_links プロジェクトスコープを持つ閲覧者だけに gitLinks: { links, total } を返します。スコープ外では キー自体がありません。認可済みで未リンクなら { links: [], total: 0 } です。

{"gitLinks":{"links":[{"id":"uuid","kind":"pr","ref":"123","title":"NOLTO-50 対応","author":"Developer","committedAt":"2026-09-06 00:00:00+00","url":"https://github.com/org/repo/pull/123"}],"total":1}}

最新50件(committedAt 降順、null は後、同時刻は作成日時降順)を返します。author、committedAt、url は null の場合があります。取り込みは Git links API を参照してください。表示設定 summary は hash / PR 番号と日付だけ、full は件名・作者も表示します。設定は API 行のフィールドを削るものではありません。外部スコープには URL・件数・存在の事実も返しません。

関連課題

同じ project の課題を親子とは別の関係で結びます。詳細 GET のトップレベル related: IssueLinkRef[] に、両側から相手の課題が返ります。各行の deleted は削除済みかどうかを示し、true の場合 subject は空文字です。削除済み相手の関連解除はできますが、新たな関連先には指定できません。

POST/api/projects/{projectId}/issues/{number}/links書く

issueKey または issueId のどちらか一方を JSON body に指定します。

status意味
201関連を追加。応答は related の配列を持つオブジェクト
200同じペアは追加済み(逆方向からの追加も同じ関連)
400入力不正、または issue_link_self(自分自身)
403書き込み権限なし
404課題が存在しない、または別 project
DELETE/api/projects/{projectId}/issues/{number}/links/{linkedIssueId}書く

関連を解除し、残った related を 200 で返します。関連が存在しない場合は 404 です。

関連課題は一括操作の対象外です。通知は送信せず、追加・解除時にそれぞれ issue_link_added / issue_link_removed を活動記録へ残します。重複追加で記録は増えません。

バックリンク

GET/api/projects/{projectId}/issues/{number}/backlinks読む

この課題に言及する課題本文・コメント・Wiki を更新日時の新しい順に返します。

offset は 0 以上の整数(既定 0)。1 ページは最大 10 件で、応答は BacklinksPage です。負数・不正な値は 400、末尾を超える offset は空配列と nextOffset: null を返します。無効な機能や scope 外の言及は total にも含めません。削除済みコメントは表示しません。

BacklinkItem.issueKey は課題・コメント行にだけ含まれるフル課題キーです。Wiki 行には含みません。

本文保存時に同一 project の課題キー、attachment: と UUID、Wiki ページ URL を索引化します。コードフェンス・インラインコード内は除外します。未作成の課題キーは、参照元本文を再編集するまで索引に入りません。

プレビュー

GET/api/projects/{projectId}/issues/preview読む

keys にカンマ区切りのフル課題キーを指定し、閲覧可能な課題の概要をまとめて取得します。

大文字小文字は不問で、重複と空トークンを除いた最大 50 キーを受け付けます(例: ?keys=NOLTO-12,nolto-34)。応答は items: IssuePreview[] を持つオブジェクトです。未知・別 project のキーは省略します。削除済み(ゴミ箱内)の課題は省略されます。

{
  "items": [{
    "key": "NOLTO-12",
    "number": 12,
    "subject": "ログイン画面の文言",
    "type": { "id": "type-uuid", "name": "課題", "color": "#6b7280" },
    "status": { "id": "status-uuid", "name": "未対応", "color": "#6b7280", "isClosed": false },
    "priority": "normal",
    "assignee": { "id": "user-uuid", "name": "山田 太郎", "email": null },
    "dueDate": "2026-09-06",
    "updatedAt": "2026-09-05T00:00:00Z",
    "excerpt": "見出し\n本文一行目"
  }]
}

人物は閲覧者に応じてマスクします。上の例は member 視点で、内部 owner / admin または本人以外には担当者の email を null として返します。

excerpt は本文の先頭 4,000 文字から Markdown 記法・コード・画像・添付リンクを除き、空行を飛ばした冒頭 3 行です。各行 120 文字、全体 300 文字を超える場合は末尾を … に置き換えます。文字数はコードポイント単位です。

status意味
200取得成功。不明なキーだけなら items は空配列
400keys 省略・空・不正、または重複除去後 51 件以上
401未認証
403project のメンバーではない
404project なし、課題機能無効、または issues scope 外

ボード

GET/api/projects/{projectId}/issues/board読む

全状態を列にしたカンバンボード用データを返します。一覧と同じ query を使えますが、status / closed / page は無視します。

{
  "columns": [
    {
      "status": { "id": "status-uuid", "name": "処理中", "color": "#ca8a04", "isClosed": false },
      "issues": [{ "id": "issue-uuid", "number": 12, "key": "NOLTO-12", "subject": "ログイン画面の文言" }]
    }
  ],
  "total": 1,
  "truncated": false
}
status意味
200状態列と課題。500 件で打ち切り、超過時は truncated: true
404project が見つからない、または課題機能が無効

コメント

IssueComment.via は、作成時に API トークンを使った場合 { "kind": "api_token", "tokenName": "CI agent" }、OAuth で接続したアプリを使った場合 { "kind": "oauth_app", "tokenName": "Claude" }、Web/Cookie の場合 null です。tokenName は、API トークンではトークン名、OAuth アプリではアプリ名です。アプリ名には (MCP) の接尾辞は付きません。課題詳細の comments[] とコメントの作成・編集応答に含まれ、属性変更履歴も同じ形式です。コメントの編集・削除、トークン名の変更や失効で作成時の値は変わりません。Web では API トークンは「API 経由」、OAuth アプリは「Claude 経由」のようなバッジを表示し、title はそれぞれ「API トークン: (トークン名)」「接続中のアプリ: (アプリ名)」です。アプリ名は書式文字を除いて前後の空白を取り、バッジでは24字を超える分を … に省略します。title には省略せず表示し、空の名前では「アプリ経由」、title は「接続中のアプリ」です。削除済みコメントではバッジを表示しません。

POST/api/projects/{projectId}/issues/{number}/comments書く

課題へコメントを追加します。

{
  "body": "確認しました。",
  "attachmentIds": ["attachment-uuid"]
}

body は必須で 1〜100,000 文字、attachmentIds は 20 件までです。

status意味
201{ "comment": IssueComment }
400本文または添付が不正
404課題が見つからない
PATCH/api/projects/{projectId}/issues/{number}/comments/{commentId}自分 / admin

自分のコメント本文を更新します。owner / admin は他の member のコメントも更新できます。

{
  "body": "確認して対応しました。"
}
status意味
200{ "comment": IssueComment }
403他人のコメントを変更する権限がない
404コメントが見つからない
DELETE/api/projects/{projectId}/issues/{number}/comments/{commentId}自分 / admin

自分のコメントを削除します。owner / admin は他の member のコメントも削除できます。

フィールド変更を伴わない通常コメントも tombstone として残ります。行は削除されず、body は空になり、deletedAt と deletedBy が設定されます。削除前の本文は GET …/revisions で owner / admin だけが確認できます。

フィールド変更を含むコメントを削除した場合も本文だけが tombstone に置き換わり、changes は残ります。本文がなく変更履歴だけの行は削除できません。コメントの添付は解放されます。既に削除されたコメントへの DELETE / PATCH は 409 comment_deleted です。

status意味
204tombstone 化に成功
403削除権限がない
404コメントが見つからない
409history_only または comment_deleted
GET/api/projects/{projectId}/issues/{number}/comments/{commentId}/revisions読む

コメントの編集・削除履歴を新しい順に返します。owner / admin は削除済みコメントの履歴も参照できます。

{
  "revisions": [
    {
      "revision": 2,
      "kind": "edit",
      "body": "変更前の本文",
      "editedBy": { "id": "user-uuid", "email": null, "name": "山田" },
      "createdAt": "2026-09-03T01:23:45.678Z"
    }
  ]
}
status意味
200{ "revisions": CommentRevision[] }
403forbidden。削除済みコメントの履歴を参照する権限がない
404コメントが見つからない、または課題機能が無効

本文やコメントに [@表示名](mention:<userId>) と書くと、同じ project の member へメールで通知します。member ではない利用者と操作した本人は通知対象外です。編集時は新たに追加したメンションだけを通知します。

ウォッチ

課題の関係者(作成者・担当者・メンションされた人・コメントした人)は自動でウォッチャーになり、以後の更新が通知されます。手動での切り替えは次の 2 つです。明示的に解除した課題は、以後の自動登録では復活しません。

PUT/api/projects/{projectId}/issues/{number}/watch読む

課題をウォッチします。viewer も使えます。

DELETE/api/projects/{projectId}/issues/{number}/watch読む

ウォッチを解除します。未ウォッチでも 200 です(冪等)。

{
  "watching": true,
  "watcherCount": 3,
  "watchers": [{ "id": "user-uuid", "email": null, "name": "山田 花子" }]
}
status意味
200切替後の自分の状態、ウォッチャー数、現メンバーのウォッチャー一覧
404課題が見つからない

他のメンバーをウォッチャーに追加・解除

POST/api/projects/{projectId}/issues/{number}/watchers書く

現在の project member を1回に1〜20人、ウォッチャーへ追加します。明示的に解除済みの人も再びウォッチ中になります。

{ "userIds": ["user-uuid"] }

レスポンスは自分の watching、watcherCount、watchers に加え、今回新たにウォッチ中になった利用者を返します。

{ "watching": true, "watcherCount": 3, "watchers": [], "added": ["user-uuid"] }
DELETE/api/projects/{projectId}/issues/{number}/watchers/{userId}読む

自分のウォッチは全 role が解除できます。他人のウォッチを解除できるのは owner / admin だけです。すでに未ウォッチでも成功します。

status意味
200追加・解除後のウォッチ状態と一覧
400入力不正、または watcher_not_member
403追加・解除の権限がない
404project、課題、または課題機能が見つからない

リアクション

課題本文とコメントには固定 5 種のリアクションを付けられます。viewer を含む reader が自分のリアクションだけを付け外しでき、同じリクエストを繰り返しても結果は変わりません。通知と活動記録は作成しません。

code表示意味
eyes👀見ました(対応はこれから)
+1👍承知しました / 進めてください
pray🙏ありがとうございます
tada🎉完了・リリースおめでとう
confused😕認識が合っていないかも(要相談)
PUT/api/projects/{projectId}/issues/{number}/reactions/{emoji}読む

課題本文へリアクションを付けます。

DELETE/api/projects/{projectId}/issues/{number}/reactions/{emoji}読む

課題本文から自分のリアクションを外します。

PUT/api/projects/{projectId}/issues/{number}/comments/{commentId}/reactions/{emoji}読む

コメントへリアクションを付けます。削除済みコメントには付けられません。

DELETE/api/projects/{projectId}/issues/{number}/comments/{commentId}/reactions/{emoji}読む

コメントから自分のリアクションを外します。削除済みコメントへの DELETE は 409 で、既存行は変更しません。

{
  "reactions": [
    {
      "emoji": "+1",
      "count": 2,
      "users": [
        { "id": "user-uuid", "email": null, "name": "山田" },
        { "id": "user-uuid-2", "email": null, "name": "佐藤" }
      ],
      "reactedByMe": true
    }
  ]
}

0 件の種類は含めません。users は付けた順です。

status意味
200更新後の対象の { reactions }
403project を読む権限がない
404課題・コメント・絵文字が見つからない、課題機能が無効、または機能スコープ外
409削除済みコメント(comment_deleted)

課題設定

kind は types / statuses / categories のいずれかです。

GET/api/projects/{projectId}/issue-settings読む

project の種別、状態、カテゴリを表示順で返します。

{
  "types": [{ "id": "uuid", "name": "タスク", "color": "#2563eb", "sortOrder": 0, "isDefault": true, "bodyTemplate": "## 再現手順\n\n1. " }],
  "statuses": [{ "id": "uuid", "name": "未対応", "color": "#64748b", "sortOrder": 0, "isDefault": true, "isClosed": false }],
  "categories": [{ "id": "uuid", "name": "UI", "sortOrder": 0 }]
}

types.bodyTemplate は Markdown の本文テンプレートで、null は未設定です。statuses と categories にはこのフィールドはありません。

status意味
200課題設定
404project が見つからない、または課題機能が無効
POST/api/projects/{projectId}/issue-settings/{kind}admin

種別、状態、カテゴリの項目を追加します。

kindbody
typesname(1〜50)、任意の color(小文字 #rrggbb)/ isDefault / bodyTemplate(Markdown、20,000文字以内、null で未設定)
statusesname(1〜50)、任意の color(小文字 #rrggbb)/ isDefault / isClosed
categoriesname(1〜50)
{
  "name": "レビュー中",
  "color": "#ca8a04",
  "isClosed": false
}
status意味
201作成した item(種別・状態・カテゴリのいずれか)
400kind または入力が不正
409同じ名前の項目がある
PATCH/api/projects/{projectId}/issue-settings/{kind}/{id}admin

項目を更新します。作成時のフィールドか sortOrder を 1 つ以上指定します。types は bodyTemplate も更新できます(null で解除)。

{
  "name": "確認中",
  "sortOrder": 20
}

sortOrder は 0〜1000 です。

status意味
200更新した item(種別・状態・カテゴリのいずれか)
400kind、ID、入力が不正
409既定の項目を isDefault: false にしようとした
DELETE/api/projects/{projectId}/issue-settings/{kind}/{id}?replaceWithId={id}admin

項目を削除します。使用中の項目には付け替え先の replaceWithId が必要です。

status意味
204削除済み
400付け替え先が未指定、自分自身、または存在しない
409既定の項目、または kind の最後の項目で削除できない

活動記録

API トークンで行った操作の payload.via は { "kind": "api_token", "tokenName": "CI agent" }、OAuth アプリでは { "kind": "oauth_app", "tokenName": "Claude" } です。tokenName にはそれぞれ操作時のトークン名・アプリ名が入り、アプリ名には (MCP) の接尾辞は付きません。編集・削除は操作時の経路を記録します。Web のバッジと title はコメントと同じ表示です。Cookie/システム操作の payload は従来のままで、既存の文字列 via を含む場合もあります。トークンの平文・hash は返しません。

GET/api/projects/{projectId}/activityowner / admin

project の変更イベントを新しい順に返します。entityType はカンマ区切りで project / member / issue / comment / wiki / file / folder / attachment を指定できます。limit 既定 50、最大 200、cursor は before + beforeId です。

{
  "events": [
    {
      "id": "event-uuid",
      "actor": { "id": "user-uuid", "name": "山田" },
      "entityType": "comment",
      "entityId": "comment-uuid",
      "action": "deleted",
      "payload": { "key": "NOLTO-19", "number": 19, "commentId": "comment-uuid" },
      "createdAt": "2026-09-03T01:23:45.678000Z"
    }
  ],
  "nextCursor": { "before": "2026-09-03T01:23:45.678000Z", "beforeId": "event-uuid" }
}
status意味
200{ "events": ActivityEvent[], "nextCursor": ActivityCursor }(最終ページは nextCursor が null)
401ログインが必要
403owner / admin ではない

Slack 連携

組織設定で「Slack に追加」から Slack App を接続し、プロジェクトごとに通知先チャンネルを選びます。接続と切断には組織 admin 権限が必要です。

GET/api/integrations/slack/installadmin

orgId を指定し、ブラウザで全画面遷移します。Slack の認可画面へ 302 リダイレクトします。

認可後は組織設定へ戻ります。成功時は ?slack=connected&team=…#slack、失敗時は ?slack=error&reason=…#slack が付きます。

GET/api/orgs/{orgId}/slack-installationsadmin

組織の Slack 接続一覧を返します。

{
  "installations": [
    { "id": "uuid", "teamName": "Uruca", "status": "active", "installedAt": "2026-09-18T00:00:00Z", "installedByName": "田中", "projectCount": 3, "channelCount": 5 }
  ]
}

status は active / revoked、installedByName は null の場合があります。

DELETE/api/orgs/{orgId}/slack-installations/{installationId}admin

組織の Slack 接続と、その接続を使う通知チャネルを削除します。

切断成功時は 204、接続が見つからない場合は 404 を返します。

GET/api/projects/{projectId}/slack-channelsadmin

プロジェクトで利用できる Slack 接続ごとに、通知先のチャンネル候補を返します。owner / admin のみ取得できます。

{
  "workspaces": [
    {
      "installationId": "uuid",
      "teamName": "Uruca",
      "channels": [{ "id": "C123ABC", "name": "general", "isPrivate": false, "memberCount": 128 }],
      "fetchedAt": "2026-09-18T00:00:00Z",
      "truncated": false,
      "status": "active"
    }
  ]
}

候補は 60 秒間キャッシュされます。?refresh=1 で再取得できます。プライベートチャンネルは Nolto を招待したものだけが対象です。Slack で /invite @Nolto を実行してください。アーカイブ済みのチャンネルは候補に含みません。

memberCount は省略される場合があります。truncated: true は取得上限に達し、未取得の候補があることを示します。status: "revoked" の接続では channels は空配列、fetchedAt は null です。Slack からの取得に失敗すると 502 を返します。

通知チャネル

プロジェクトの課題イベント(作成・更新・コメント)を、接続済みの Slack App から選択したチャンネルへ全件投稿します。owner / admin のみ操作できます。

GET/api/projects/{projectId}/notification-channelsadmin

通知チャネルと、プロジェクトで利用できる Slack 接続の一覧を返します。

{
  "channels": [
    {
      "id": "uuid",
      "name": "開発通知",
      "installationId": "uuid",
      "teamName": "Uruca",
      "slackChannelId": "C123ABC",
      "slackChannelName": "general",
      "isPrivate": false,
      "enabled": true,
      "roadmapEvents": false,
      "lastError": null,
      "disabledAt": null,
      "createdAt": "2026-09-18T00:00:00Z"
    }
  ],
  "installations": [{ "id": "uuid", "teamName": "Uruca", "status": "active" }]
}

lastError は Slack のエラーコード、disabledAt は自動停止した日時です。エラーや自動停止がなければ null です。旧形式の通知チャネルでは installationId / teamName / slackChannelId / slackChannelName が null の場合があります。

POST/api/projects/{projectId}/notification-channelsadmin

通知チャネルを登録します。保存前にチャンネル情報を確認してテスト投稿を送り、失敗すると保存しません。

{ "installationId": "uuid", "channelId": "C123ABC", "name": "開発通知" }

installationId / channelId は必須です。name は省略または空文字なら Slack のチャンネル名を使います。名前は最大 60 文字です。

status意味
201{ "channel": ... }(一覧と同じチャネル形式)
400入力が不正、利用できない接続、同じチャンネルの重複、または上限(10 件)超過
422Slack のチャンネル情報の確認またはテスト投稿に失敗

422 のメッセージは Slack 側の原因によって変わります。

Slack 側の原因メッセージ
not_in_channelこのチャンネルに Nolto が参加していません。Slack で /invite @Nolto を実行してから追加してください。
channel_not_foundチャンネルが見つかりません。選び直してください。
is_archivedこのチャンネルはアーカイブ済みです。
その他Slack への投稿に失敗しました。時間をおいて試してください。
PATCH/api/projects/{projectId}/notification-channels/{channelId}admin

name / enabled / roadmapEvents を更新します。少なくとも 1 項目を指定してください。

DELETE/api/projects/{projectId}/notification-channels/{channelId}admin

チャネルを削除します。

status意味
200 / 204更新({ "channel": ... })/ 削除済み
404チャネルが見つからない

添付

添付はクライアントから S3 へ直接アップロードします。

  1. 添付メタデータを POST し、15 分有効の uploadUrl を取得します。
  2. uploadUrl へファイル本体を PUT します。
  3. complete API を呼び、ready にします。
  4. 課題やコメントの attachmentIds に渡すか、Markdown から attachment ID を参照します。
POST/api/projects/{projectId}/attachments書く

pending 状態の添付と presigned upload URL を発行します。

{
  "filename": "screenshot.png",
  "size": 248120,
  "mime": "image/png"
}

filename は 1〜255 文字でパス区切りを含められません。size は bytes です。

{
  "attachment": { "id": "attachment-uuid", "filename": "screenshot.png", "size": 248120, "mime": "image/png", "status": "pending" },
  "uploadUrl": "https://storage.example.com/presigned-url",
  "expiresAt": "2026-08-29T03:15:00.000Z"
}
status意味
200pending 添付と upload URL
400入力不正。実行ファイルなどは禁止形式 blocked_type
402Free の project ごとの添付容量上限(100 MB)を超過
4131 ファイル 50 MB を超過
503ストレージが未設定
PUT{uploadUrl}なし

発行された URL へファイル本体を送ります。Authorization ヘッダは付けません。

status意味
200S3 へのアップロード成功
POST/api/projects/{projectId}/attachments/{attachmentId}/completeアップロード本人

S3 のオブジェクト到達とサイズを確認し、添付を ready にします。

status意味
200{ "attachment": PublicAttachment }
403アップロードした本人ではない
409upload_missing、または size_mismatch。サイズ不一致時は行とオブジェクトを削除
GET/api/projects/{projectId}/attachments/{attachmentId}/url読む

ready な添付の 5 分有効 URL を返します。画像は inline、それ以外は attachment で配信します。

redirect=1 を query に付けると URL の JSON ではなく 302 で転送します。

status意味
200{ "url": "...", "expiresAt": "..." }
302redirect=1 の転送
404添付が見つからない、または ready ではない
DELETE/api/projects/{projectId}/attachments/{attachmentId}自分 / admin

自分がアップロードした未紐付けの添付を削除します。owner / admin は他の member の未紐付け添付も削除できます。紐付いた添付は参照元の操作で unlink し、GC が回収します。

status意味
200{ "ok": true }。S3 削除に失敗しても行は deleted として残り、GC が再試行する
403削除権限がない
409attachment_linked。課題 / Wiki / File に紐付いた添付。参照元から削除してください

complete 後の ID は、自分がアップロードした ready かつ未紐付けの添付だけを attachmentIds に渡せます。本文では画像を ![name](attachment:<attachmentId>)、その他を [name](attachment:<attachmentId>) と書きます。24 時間以内に紐付けなかった添付は自動削除されます。

GET/api/projects/{projectId}/attachments/references読む

削除前に添付の参照件数を確認します。

  • attachmentId=<uuid>: { count } を返します。
  • entityType=issue|comment|wiki&entityId=<uuid>: { count, attachmentCount } を返します。自身の参照は除外し、課題ではコメントの添付と参照もまとめて扱います。

対象が別 project または存在しない場合は 404 です。本文からの参照があっても削除はブロックしません。既存の所有リンクによる attachment_linked 409 は維持します。課題・コメント・Wiki の削除確認には参照がある場合だけ警告を出し、削除後の本文では画像・リンクとも「削除済みの添付ファイル」と表示します。

保存済みフィルタ

GET/api/projects/{projectId}/issue-filters読む

自分のフィルタと、他の member が共有したフィルタを名前順で返します。

{
  "mine": [],
  "shared": []
}
status意味
200mine と shared のフィルタ一覧
POST/api/projects/{projectId}/issue-filters書く

一覧の絞り込み条件を保存します。

{
  "name": "自分の期限超過",
  "query": {
    "statusIds": [],
    "closed": "exclude",
    "assignees": ["me"],
    "typeIds": [],
    "priorities": [],
    "categoryIds": [],
    "updatedWithin": null,
    "overdue": true,
    "parent": null,
    "q": "",
    "sort": "due",
    "order": "asc"
  },
  "isShared": false
}

name は 1〜40 文字、isShared の既定は false です。query の未知のキーは 400 です。

status意味
201{ "filter": IssueFilter }
409同じ作成者に同名のフィルタがある
PATCH/api/projects/{projectId}/issue-filters/{filterId}作成者 / admin

名前、query、共有設定のいずれかを更新します。共有フィルタは owner / admin も更新できます。

{
  "name": "今週の担当課題",
  "isShared": true
}
status意味
200{ "filter": IssueFilter }
403更新権限がない
404フィルタが見つからない。他人の非共有フィルタも 404
DELETE/api/projects/{projectId}/issue-filters/{filterId}作成者 / admin

フィルタを削除します。共有フィルタは owner / admin も削除できます。

status意味
204削除済み
403削除権限がない
404フィルタが見つからない。他人の非共有フィルタも 404

SavedIssueQuery v2 は課題一覧 query から page を除いた JSON です。statusIds / typeIds / categoryIds は UUID 配列、priorities は優先度配列、assignees は UUID / me / none の配列で、各配列は20件までです。updatedWithin は "7d" / null、overdue は boolean、parent は課題番号 / none / null です。me は見る人ごとに解決します。

旧 v1 の単一値 typeId / priority / categoryId / assignee は読み取り・POST・PATCH で受け付け、v2 の配列に正規化します。レスポンスと新たに保存する JSON は v2 です。読み取りだけでは DB 行を書き換えません。v1 と v2 を混在させた query や未知のキーは 400 です。

一括操作

POST/api/projects/{projectId}/issues/bulk書く

一覧で選んだ課題、または保存済みフィルタと同じ形式の条件に合う課題を一括更新します。

target は issueIds(1〜500件)か filter のどちらかです。patch は1項目以上を指定し、addWatcherIds は20人までです。カテゴリは指定した集合で置き換え、空配列で解除します。

{
  "target": { "issueIds": ["issue-uuid-1", "issue-uuid-2"] },
  "patch": { "statusId": "status-uuid" }
}
{
  "bulkId": "bulk-uuid",
  "total": 2,
  "succeeded": 1,
  "failed": 1,
  "results": [
    { "issueId": "issue-uuid-1", "key": "NOLTO-12", "ok": true },
    { "issueId": "issue-uuid-2", "key": null, "ok": false, "code": "not_found", "message": "課題が見つかりません。" }
  ]
}
status意味
200全件失敗を含む課題ごとの結果
400入力不正、too_many_targets(total 付き)、assignee_not_member、watcher_not_member、status_invalid、category_invalid、parent_invalid
401ログインが必要
403viewer など更新権限がない
404issues flag が無効

課題ごとの code は not_found、parent_invalid、master_invalid、forbidden、conflict、invalid、internal です。課題は順に独立処理され、履歴と活動記録を課題ごとに残します。活動記録の payload.bulkId は同じ操作で共通です。変更がない課題は成功扱いで履歴を増やしません。bulk_updated 通知は課題ごとに作り、email / Slack は5分窓で集約します。

マイ課題

GET/api/me/issuesBearer Token / Cookie

ログインユーザーが参加する課題機能 ON かつ key 設定済みの project を横断し、担当・登録した課題を返します。対象 project が無ければ空配列です。

query値
roleassignee(既定)/ reporter / watching / any
dueany(既定)/ overdue / week
closedexclude(既定)/ include / only
sortdue(既定)/ project / 課題一覧と同じ値。status / type の sortOrder はプロジェクトごとの値なので、プロジェクト横断では並びの意味は保証されません
orderasc / desc。既定は due / assignee / status / type / subject のとき asc、それ以外は desc
page1 始まり

overdue は期限超過かつ未完了だけを返し、closed の指定に関わらず完了課題を除きます。week はサーバーの JST で今日から 7 日後までです。

{
  "issues": [
    {
      "id": "issue-uuid",
      "number": 12,
      "key": "NOLTO-12",
      "subject": "ログイン画面の文言",
      "project": { "id": "project-uuid", "name": "Web アプリ", "key": "NOLTO" }
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 50
}
status意味
200project 情報付きの課題一覧
401ログインが必要

watching は自分の issue_watchers.state = 'watching' の課題です。any は引き続き自分が担当または登録した課題で、ウォッチだけの課題は含みません。sort=project は order に関わらずプロジェクト名昇順、課題番号降順です。アーカイブ済みプロジェクトと削除済み課題は除外します。

GET/api/me/issues/countsBearer Token / Cookie

マイ課題の6ビューの件数を1つの集計で返します。Bearer Token は issues:read が必要で、プロジェクト制限も適用されます。

{ "counts": { "overdue": 2, "week": 3, "mine": 8, "reported": 4, "watching": 5, "all": 14 } }

overdue / week は自分の担当かつ未完了で、期限が今日より前 / 今日から7日後までの件数です。mine は自分の担当、reported は自分の登録、watching は自分のウォッチ中の未完了件数です。all は担当または登録した課題を完了込みで数えます。対象プロジェクトがなければ全項目0です。対象プロジェクトの解決と認証は /api/me/issues と共通です。

通知

自分宛のアプリ内通知です。担当・登録・メンション・ウォッチ中の課題で起きた出来事が、参加プロジェクトを横断して届きます。90 日で自動削除されます。

GET/api/me/notificationsBearer Token / Cookie

新しい順に 50 件ずつ返します。

query値
unread1 で未読のみ
before前ページ応答の nextBefore(ISO 8601)を渡すと続きを返す
{
  "notifications": [
    {
      "id": "uuid",
      "projectId": "project-uuid",
      "projectName": "Web アプリ",
      "eventType": "commented",
      "actorLabel": "花子",
      "key": "NOLTO-12",
      "subject": "ログイン画面の文言",
      "number": 12,
      "excerpt": "確認しました。",
      "createdAt": "2026-08-30T00:00:00Z",
      "readAt": null
    }
  ],
  "unreadCount": 1,
  "nextBefore": null
}

eventType は created / updated / bulk_updated / commented / comment_edited です。

POST/api/me/notifications/readBearer Token / Cookie

既読にします。{ "ids": ["uuid", ...] }(100 件まで)または { "all": true }。

status意味
200{ "updated": 件数 }
400body が不正

通知設定

メール通知の受け取り設定です。アプリ内通知は設定に関わらず記録されます。設定は送信時に適用されます。

GET/api/me/notification-settingsBearer Token / Cookie

グローバル設定と、参加プロジェクト毎の上書きを返します。emailEnabled: null はグローバル設定に従います。

{
  "emailEnabled": true,
  "projects": [
    { "projectId": "project-uuid", "name": "Web アプリ", "key": "NOLTO", "emailEnabled": null }
  ]
}
PATCH/api/me/notification-settingsBearer Token / Cookie

{ "emailEnabled": false }(グローバル)または { "projectId": "...", "emailEnabled": true | false | null }(プロジェクト上書き。null で上書きを解除)。応答は GET と同形の最新設定です。

status意味
200最新の設定
400body が不正
404参加していないプロジェクト

プロフィール

GET/api/me/profileBearer Token / Cookie

ログインユーザーのプロフィールを返します。

{
  "profile": {
    "id": "user-uuid",
    "email": "dev@example.com",
    "displayName": "山田"
  }
}
status意味
200プロフィール
401ログインが必要
PATCH/api/me/profileBearer Token / Cookie

必須の表示名を更新します。

{
  "displayName": "山田"
}

displayName は trim 後 1〜50 文字の文字列です。空・空白のみ・null・欠落・非文字列は 400 display_name_required、50 文字超は 400 display_name_invalid を返し、DB を更新しません。

status意味
200{ "profile": { "id": "...", "email": "...", "displayName": "山田" } }
400表示名が不正
401ログインが必要

型

型フィールド
IssueLinkRefid, number, key, subject, status(IssueParentRef と同形)
BacklinkItemsourceType(issue / comment / wiki), sourceId, href, label, title, updatedAt, 任意の author
BacklinksPageitems: BacklinkItem[], total: number, `nextOffset: number

各エンドポイントのレスポンスで使う主な型です。

{
  "id": "issue-uuid",
  "number": 12,
  "key": "NOLTO-12",
  "subject": "ログイン画面の文言",
  "priority": "normal",
  "type": { "id": "type-uuid", "name": "タスク", "color": "#2563eb" },
  "status": { "id": "status-uuid", "name": "処理中", "color": "#ca8a04", "isClosed": false },
  "assignee": { "id": "user-uuid", "email": null, "name": "山田" },
  "createdBy": { "id": "user-uuid", "email": null, "name": "pm***" },
  "categories": [{ "id": "category-uuid", "name": "UI" }],
  "dueDate": "2026-09-01",
  "closedAt": null,
  "createdAt": "2026-08-29T01:23:45.678Z",
  "updatedAt": "2026-08-29T02:00:00.000Z",
  "commentCount": 2,
  "parent": {
    "id": "parent-uuid",
    "number": 3,
    "key": "NOLTO-3",
    "subject": "認証まわり",
    "status": { "id": "status-uuid", "name": "処理中", "color": "#ca8a04", "isClosed": false }
  },
  "childCount": 0
}

上は IssueSummary です。IssueDetail はこれに Markdown の body と reactions を加えます。

型フィールド
IssueCommentid、author、body、changes、attachments、readReceipts、createdAt、updatedAt、deletedAt、deletedBy、revisionCount、reactions
IssueReactionemoji、count、users、reactedByMe
IssueChangefield、from、to、fromLabel、toLabel
IssueTypeid、name、color、sortOrder、isDefault
IssueStatusIssueType のフィールド + isClosed
IssueCategoryid、name、sortOrder
IssueFilterid、name、query、isShared、createdBy、updatedAt
SavedIssueQuerystatusIds、closed、assignee、typeId、priority、categoryId、parent、q、sort、order
PublicAttachmentid、filename、size、mime、status、entityType、entityId、createdAt、completedAt

PublicAttachment.status は pending / ready / deleted、entityType は issue / issue_comment / null です。IssueChange.field は subject / body / type / status / priority / assignee / due_date / categories / parent です。

コメント既読表示が有効な project では、IssueComment.readReceipts は次の形です。無効なら null です。

{
  "targets": [
    { "user": { "id": "user-uuid", "email": null, "name": "山田" }, "readAt": "2026-09-03T01:23:45.678Z" },
    { "user": { "id": "user-uuid-2", "email": null, "name": "佐藤" }, "readAt": null }
  ]
}