REST APIエンドポイント設計
概要
Issue Outsource Platformの全REST APIエンドポイント仕様。 認証にはGitLab OAuthトークン(Bearer)を使用する。
共通仕様
ベースURL
https://<PF_DOMAIN>/api/v1認証
| 認証方式 | ヘッダ形式 | 説明 |
|---|---|---|
| Bearer Token | Authorization: Bearer <access_token> | GitLab OAuth2で取得したアクセストークン |
| Webhook Token | X-Gitlab-Token: <secret> | Webhook専用(内部用) |
共通レスポンス形式
json
{
"status": "success",
"data": { ... },
"meta": {
"page": 1,
"per_page": 20,
"total": 100,
"total_pages": 5
}
}エラーレスポンス形式
json
{
"status": "error",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{ "field": "title", "message": "Title is required" }
]
}
}HTTPステータスコード
| コード | 用途 |
|---|---|
| 200 | 成功(取得・更新) |
| 201 | 成功(作成) |
| 204 | 成功(削除) |
| 400 | リクエスト不正 |
| 401 | 認証エラー |
| 403 | 権限不足 |
| 404 | リソース未存在 |
| 409 | 競合(楽観ロック等) |
| 422 | バリデーションエラー |
| 429 | レートリミット超過 |
| 500 | 内部サーバーエラー |
ページネーション
全リスト系エンドポイントで共通のクエリパラメータを使用する。
| パラメータ | 型 | デフォルト | 説明 |
|---|---|---|---|
page | int | 1 | ページ番号 |
per_page | int | 20 | 1ページあたり件数(最大100) |
sort | string | created_at | ソートフィールド |
order | string | desc | ソート順(asc / desc) |
フィルタ
各エンドポイント固有のフィルタパラメータに加え、以下の共通フィルタを提供する。
| パラメータ | 型 | 説明 |
|---|---|---|
search | string | キーワード検索(タイトル・説明) |
created_after | datetime | 作成日の下限 |
created_before | datetime | 作成日の上限 |
ロール定義
| ロール | 説明 |
|---|---|
admin | プラットフォーム管理者 |
owner | プロジェクトオーナー(発注者) |
engineer | 委託エンジニア(受注者) |
reviewer | レビュアー |
public | 未認証ユーザー |
エンドポイント一覧
認証 (/auth)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /auth/gitlab | GitLab OAuth認証開始 | 不要 | public |
| GET | /auth/gitlab/callback | OAuthコールバック | 不要 | public |
| POST | /auth/refresh | トークンリフレッシュ | 要 | all |
| POST | /auth/logout | ログアウト | 要 | all |
| GET | /auth/me | 現在のユーザー情報 | 要 | all |
プロジェクト (/projects)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /projects | プロジェクト一覧 | 要 | all |
| POST | /projects | プロジェクト作成 | 要 | admin, owner |
| GET | /projects/:id | プロジェクト詳細 | 要 | all |
| PUT | /projects/:id | プロジェクト更新 | 要 | admin, owner |
| DELETE | /projects/:id | プロジェクト削除 | 要 | admin |
| POST | /projects/:id/sync | GitLabと手動同期 | 要 | admin, owner |
Issue (/issues)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /projects/:project_id/issues | Issue一覧 | 要 | all |
| POST | /projects/:project_id/issues | Issue作成 | 要 | admin, owner |
| GET | /issues/:id | Issue詳細 | 要 | all |
| PUT | /issues/:id | Issue更新 | 要 | admin, owner |
| DELETE | /issues/:id | Issue削除 | 要 | admin |
| POST | /issues/:id/sync | GitLabと手動同期 | 要 | admin, owner |
| GET | /issues/:id/comments | Issueコメント一覧 | 要 | all |
| POST | /issues/:id/comments | コメント追加 | 要 | all |
アサイン (/assignments)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /issues/:issue_id/assignments | アサイン一覧 | 要 | all |
| POST | /issues/:issue_id/assignments | アサイン申請 | 要 | engineer |
| PUT | /assignments/:id | アサイン承認・却下 | 要 | admin, owner |
| DELETE | /assignments/:id | アサイン取消 | 要 | admin, owner, engineer(自分) |
| GET | /assignments/me | 自分のアサイン一覧 | 要 | engineer |
レビュー (/reviews)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /issues/:issue_id/reviews | レビュー一覧 | 要 | all |
| GET | /reviews/:id | レビュー詳細 | 要 | all |
| PUT | /reviews/:id | レビュー結果登録 | 要 | admin, reviewer |
| GET | /reviews/:id/comments | レビューコメント一覧 | 要 | all |
| POST | /reviews/:id/comments | レビューコメント追加 | 要 | reviewer, engineer |
報酬 (/rewards)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /rewards | 報酬一覧 | 要 | admin, owner |
| GET | /rewards/me | 自分の報酬一覧 | 要 | engineer |
| GET | /rewards/:id | 報酬詳細 | 要 | admin, owner, engineer(自分) |
| PUT | /rewards/:id/status | 報酬ステータス更新 | 要 | admin |
| GET | /rewards/summary | 報酬サマリー | 要 | admin, owner |
ダッシュボード (/dashboard)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| GET | /dashboard/overview | 概要統計 | 要 | all |
| GET | /dashboard/issues/stats | Issue統計 | 要 | admin, owner |
| GET | /dashboard/engineers/stats | エンジニア統計 | 要 | admin, owner |
| GET | /dashboard/rewards/stats | 報酬統計 | 要 | admin, owner |
| GET | /dashboard/me | マイダッシュボード | 要 | engineer |
Webhook (/webhooks)
| メソッド | パス | 説明 | 認証 | ロール |
|---|---|---|---|---|
| POST | /webhooks/gitlab | GitLab Webhook受信 | Webhook Token | - |
| GET | /webhooks/events | Webhookイベント履歴 | 要 | admin |
| GET | /webhooks/events/:id | イベント詳細 | 要 | admin |
| POST | /webhooks/events/:id/retry | イベント再処理 | 要 | admin |
エンドポイント詳細
POST /auth/gitlab - GitLab OAuth認証開始
GitLab OAuthの認証URLへリダイレクトする。
レスポンス:
HTTP/1.1 302 Found
Location: https://gitlab.ethan-tech.jp/oauth/authorize?client_id=...&redirect_uri=...&response_type=code&scope=api+read_userGET /auth/gitlab/callback - OAuthコールバック
クエリパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
code | string | 認証コード |
state | string | CSRF対策用state |
レスポンス (200):
json
{
"status": "success",
"data": {
"access_token": "pf_xxxxx",
"refresh_token": "pf_ref_xxxxx",
"expires_in": 3600,
"user": {
"id": "uuid",
"gitlab_user_id": 14,
"username": "take.otani",
"display_name": "大谷剛弘",
"avatar_url": "https://...",
"role": "owner"
}
}
}GET /auth/me - 現在のユーザー情報
レスポンス (200):
json
{
"status": "success",
"data": {
"id": "uuid",
"gitlab_user_id": 14,
"username": "take.otani",
"display_name": "大谷剛弘",
"email": "take@example.com",
"avatar_url": "https://...",
"role": "owner",
"created_at": "2026-01-01T00:00:00Z"
}
}POST /projects - プロジェクト作成
リクエスト:
json
{
"name": "Issue Outsource PF",
"description": "Issue駆動開発の業務委託プラットフォーム",
"gitlab_project_id": 78,
"gitlab_project_url": "https://gitlab.ethan-tech.jp/aieo/issueoutsourcing",
"default_reward_currency": "JPY",
"settings": {
"auto_sync": true,
"sync_labels": true,
"sync_milestones": true,
"reward_label_prefix": "reward:"
}
}レスポンス (201):
json
{
"status": "success",
"data": {
"id": "uuid",
"name": "Issue Outsource PF",
"description": "Issue駆動開発の業務委託プラットフォーム",
"gitlab_project_id": 78,
"gitlab_project_url": "https://gitlab.ethan-tech.jp/aieo/issueoutsourcing",
"status": "active",
"settings": {
"auto_sync": true,
"sync_labels": true,
"sync_milestones": true,
"reward_label_prefix": "reward:"
},
"created_at": "2026-03-28T00:00:00Z",
"updated_at": "2026-03-28T00:00:00Z"
}
}POST /projects/:project_id/issues - Issue作成
リクエスト:
json
{
"title": "GitLab連携API設計",
"description": "GitLab Webhook受信とREST APIの設計",
"labels": ["api", "design"],
"difficulty": "medium",
"reward_amount": 10000,
"reward_currency": "JPY",
"milestone": "v1.0",
"deadline": "2026-04-15T00:00:00Z",
"sync_to_gitlab": true
}レスポンス (201):
json
{
"status": "success",
"data": {
"id": "uuid",
"project_id": "uuid",
"gitlab_issue_id": 649,
"gitlab_issue_iid": 5,
"title": "GitLab連携API設計",
"description": "GitLab Webhook受信とREST APIの設計",
"status": "open",
"labels": ["api", "design"],
"difficulty": "medium",
"reward": {
"amount": 10000,
"currency": "JPY"
},
"milestone": "v1.0",
"deadline": "2026-04-15T00:00:00Z",
"assignee": null,
"created_at": "2026-03-28T00:00:00Z",
"updated_at": "2026-03-28T00:00:00Z",
"gitlab_url": "https://gitlab.ethan-tech.jp/aieo/issueoutsourcing/-/issues/5"
}
}GET /projects/:project_id/issues - Issue一覧
フィルタパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
status | string | open, assigned, in_review, completed, closed |
labels | string | カンマ区切りのラベル |
difficulty | string | easy, medium, hard |
assignee_id | uuid | アサインされたユーザーID |
reward_min | int | 報酬下限 |
reward_max | int | 報酬上限 |
has_reward | bool | 報酬付きのみ |
レスポンス (200):
json
{
"status": "success",
"data": [
{
"id": "uuid",
"title": "GitLab連携API設計",
"status": "open",
"labels": ["api", "design"],
"difficulty": "medium",
"reward": {
"amount": 10000,
"currency": "JPY"
},
"assignee": null,
"created_at": "2026-03-28T00:00:00Z",
"gitlab_url": "https://gitlab.ethan-tech.jp/aieo/issueoutsourcing/-/issues/5"
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 12,
"total_pages": 1
}
}POST /issues/:issue_id/assignments - アサイン申請
リクエスト:
json
{
"message": "Claude Codeを使って対応します。2日以内に完了見込みです。",
"estimated_hours": 8
}レスポンス (201):
json
{
"status": "success",
"data": {
"id": "uuid",
"issue_id": "uuid",
"engineer_id": "uuid",
"status": "pending",
"message": "Claude Codeを使って対応します。2日以内に完了見込みです。",
"estimated_hours": 8,
"created_at": "2026-03-28T00:00:00Z"
}
}PUT /assignments/:id - アサイン承認・却下
リクエスト:
json
{
"status": "approved",
"message": "承認します。ブランチを作成してください。"
}レスポンス (200):
json
{
"status": "success",
"data": {
"id": "uuid",
"issue_id": "uuid",
"engineer_id": "uuid",
"status": "approved",
"approved_at": "2026-03-28T01:00:00Z",
"gitlab_assignee_synced": true
}
}GET /reviews/:id - レビュー詳細
レスポンス (200):
json
{
"status": "success",
"data": {
"id": "uuid",
"issue_id": "uuid",
"gitlab_mr_id": 200,
"gitlab_mr_iid": 10,
"title": "feat: Issue #5 GitLab連携API実装",
"status": "pending",
"source_branch": "feature/issue-5",
"target_branch": "main",
"pipeline_status": "success",
"comments_count": 3,
"created_at": "2026-03-28T00:00:00Z",
"gitlab_url": "https://gitlab.ethan-tech.jp/aieo/issueoutsourcing/-/merge_requests/10"
}
}PUT /reviews/:id - レビュー結果登録
リクエスト:
json
{
"status": "approved",
"comment": "LGTM。マージします。"
}レスポンス (200):
json
{
"status": "success",
"data": {
"id": "uuid",
"status": "approved",
"reviewed_at": "2026-03-28T02:00:00Z",
"reviewer_id": "uuid",
"reward_triggered": true
}
}GET /rewards/me - 自分の報酬一覧
フィルタパラメータ:
| パラメータ | 型 | 説明 |
|---|---|---|
status | string | confirmed, processing, paid, cancelled |
period_start | date | 期間開始日 |
period_end | date | 期間終了日 |
レスポンス (200):
json
{
"status": "success",
"data": [
{
"id": "uuid",
"issue_id": "uuid",
"issue_title": "GitLab連携API設計",
"amount": 10000,
"currency": "JPY",
"status": "confirmed",
"confirmed_at": "2026-03-28T03:00:00Z",
"paid_at": null
}
],
"meta": {
"page": 1,
"per_page": 20,
"total": 5,
"total_pages": 1
}
}GET /dashboard/overview - 概要統計
レスポンス (200):
json
{
"status": "success",
"data": {
"issues": {
"total": 50,
"open": 20,
"assigned": 15,
"in_review": 8,
"completed": 7
},
"engineers": {
"total": 30,
"active": 12
},
"rewards": {
"total_amount": 500000,
"currency": "JPY",
"pending_amount": 100000,
"paid_amount": 400000
}
}
}GET /dashboard/me - マイダッシュボード
レスポンス (200):
json
{
"status": "success",
"data": {
"active_assignments": [
{
"issue_id": "uuid",
"issue_title": "GitLab連携API設計",
"status": "in_progress",
"deadline": "2026-04-15T00:00:00Z",
"reward_amount": 10000
}
],
"pending_reviews": [
{
"review_id": "uuid",
"mr_title": "feat: Issue #5 GitLab連携API実装",
"status": "pending"
}
],
"reward_summary": {
"total_earned": 150000,
"pending_payment": 30000,
"currency": "JPY"
},
"recent_activity": [
{
"type": "assignment_approved",
"message": "Issue #5 のアサインが承認されました",
"created_at": "2026-03-28T01:00:00Z"
}
]
}
}レートリミット
| 対象 | 制限 | ウィンドウ |
|---|---|---|
| 認証済みユーザー | 1000リクエスト | 1時間 |
| 未認証 | 60リクエスト | 1時間 |
| Webhook | 制限なし(署名検証で制御) | - |
レートリミット超過時:
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711584000