APIドキュメント
OpenAPI 3.1.0仕様に基づくREST APIドキュメント
API概要
PowerPoint翻訳ツールのAPIは、PPTXファイルのアップロード、テキスト抽出、翻訳、ダウンロードなどの機能を提供します。
認証
APIはSupabase JWTトークンを使用したBearer認証をサポートしています。リクエストヘッダーに Authorization: Bearer <token> を含めてください。
ベースURL
現在のベースURL: https://trans-ppt.work
主要エンドポイント
ファイルアップロード(Server Action)
PPTXファイルのアップロードはServer Action経由で行います。最大25MBまで対応しています。API Routeとしての直接呼び出しはできません。
extractTextFromPPTXAction (Server Action)
アップロードされたPPTXファイルからテキスト要素を抽出します。Server Action経由で呼び出します。
// Server Action (extractTextFromPPTXAction)
// クライアントコンポーネントから直接呼び出し可能
import { extractTextFromPPTXAction } from "@/app/actions/pptx";
const result = await extractTextFromPPTXAction(fileId, filePath);POST /api/translate
指定されたテキストを目標言語に翻訳します。バッチ翻訳にも対応しています。
curl -X POST https://trans-ppt.work/api/translate/stream \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"texts": [{"id": "1", "text": "Hello"}],
"targetLanguage": "ja"
}'DELETE /api/files/{id}
指定されたIDのファイルを削除します。
curl -X DELETE https://trans-ppt.work/api/files/{id} \
-H "Authorization: Bearer <token>"GET /api/health
システムの健全性を確認します。認証は不要です。
curl https://trans-ppt.work/api/healthOpenAPI仕様書
完全なOpenAPI仕様書は以下のリンクからダウンロードまたは表示できます。
openapi: 3.1.0
info:
title: PPT Translation API
version: 1.0.0
description: |
PowerPoint プレゼンテーション翻訳サービスのAPI仕様書
このAPIは、PPTXファイルのアップロード、テキスト抽出、翻訳、ダウンロードなどの機能を提供します。
contact:
name: API Support
license:
name: MIT
identifier: MIT
servers:
- url: "{baseUrl}"
description: |
本番環境: NEXT_PUBLIC_APP_URL で決定される。
デプロイ前に実際のURLへ差し替えること。
variables:
baseUrl:
default: http://localhost:3000
description: アプリケーションのベースURL(環境変数 NEXT_PUBLIC_APP_URL)
- url: http://localhost:3000
description: 開発環境
tags:
- name: Files
description: ファイル操作関連のエンドポイント
- name: Translation
description: 翻訳関連のエンドポイント
- name: Preview
description: ハイブリッドプレビュー関連のエンドポイント(PDF/サムネイル生成)
- name: Auth
description: 認証関連のエンドポイント
- name: Stripe
description: Stripe決済・サブスクリプション関連のエンドポイント
- name: Health
description: ヘルスチェック関連のエンドポイント
- name: Admin
description: 管理者専用エンドポイント(withAdminGetHandler / withAdminPostHandler 経由)
paths:
# NOTE: ファイルアップロード・一覧取得はServer Action(src/app/actions/)で実装。
# GET /api/files(一覧)は Issue #403 完了に伴い削除済み。
/api/files/{id}:
delete:
summary: ファイルを削除
description: 指定されたIDのファイルを削除します。
operationId: deleteFile
x-audience: public
x-auth: cookie
tags:
- Files
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
description: ファイルID
schema:
type: string
format: uuid
responses:
'200':
description: 削除成功
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/api/translate/jobs:
post:
summary: durable翻訳ジョブを作成
operationId: createTranslationJob
x-audience: public
x-auth: cookie
tags: [Translation]
security: [{ CookieAuth: [] }]
parameters:
- name: Idempotency-Key
in: header
required: false
schema: { type: string, minLength: 1, maxLength: 255 }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobCreateRequest' }
responses:
'202':
description: queued job
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'500': { $ref: '#/components/responses/InternalServerError' }
/api/translate/jobs/{jobId}:
get:
summary: durable翻訳ジョブ状態を取得
operationId: getTranslationJob
x-audience: public
x-auth: cookie
tags: [Translation]
security: [{ CookieAuth: [] }]
parameters:
- $ref: '#/components/parameters/TranslationJobId'
responses:
'200':
description: owner-scoped job status
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
'500': { $ref: '#/components/responses/InternalServerError' }
/api/translate/jobs/{jobId}/cancel:
post:
summary: durable翻訳ジョブをキャンセル
operationId: cancelTranslationJob
x-audience: public
x-auth: cookie
tags: [Translation]
security: [{ CookieAuth: [] }]
parameters: [{ $ref: '#/components/parameters/TranslationJobId' }]
responses:
'200':
description: cancelled job
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/translate/jobs/{jobId}/retry:
post:
summary: durable翻訳ジョブを同じjobで再試行
operationId: retryTranslationJob
x-audience: public
x-auth: cookie
tags: [Translation]
security: [{ CookieAuth: [] }]
parameters: [{ $ref: '#/components/parameters/TranslationJobId' }]
responses:
'200':
description: requeued job
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobResponse' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'409': { $ref: '#/components/responses/Conflict' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/translate/jobs/{jobId}/terminal-notice/claim:
post:
summary: terminal toast表示権を原子的にclaim
operationId: claimTranslationJobTerminalNotice
x-audience: public
x-auth: cookie
tags: [Translation]
security: [{ CookieAuth: [] }]
parameters: [{ $ref: '#/components/parameters/TranslationJobId' }]
responses:
'200':
description: claim result
content:
application/json:
schema: { $ref: '#/components/schemas/TranslationJobTerminalNoticeClaim' }
'400': { $ref: '#/components/responses/BadRequest' }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'404': { $ref: '#/components/responses/NotFound' }
'429': { $ref: '#/components/responses/TooManyRequests' }
/api/translate/single:
post:
summary: 単一テキストを翻訳
description: |
単一テキストを目標言語に翻訳します。
優先度キュー対応、DBキャッシュ統合、AbortSignal対応。
operationId: translateSingle
x-audience: public
x-auth: cookie
tags:
- Translation
security:
- CookieAuth: []
parameters:
- name: Idempotency-Key
in: header
required: false
description: 同一リクエストの再送を識別する冪等性キー
schema:
type: string
minLength: 1
maxLength: 255
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationRequest'
responses:
'200':
description: 翻訳成功
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'400':
description: 入力エラー
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'401':
description: 認証エラー
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'403':
description: 翻訳機能または権限が利用できない
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'404':
description: 対象ファイルが見つからない
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'409':
description: 同一の冪等性キーで翻訳処理中
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'422':
description: 冪等性キーのリクエスト不一致
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'429':
description: レート制限を超過
headers:
Retry-After:
description: 再試行可能になるまでの秒数
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'499':
description: クライアントによる翻訳キャンセル(サーバー側観測用。クライアントabort後は通常このレスポンスを受信しない)
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'500':
description: 翻訳エラー
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
'503':
description: 翻訳機能停止中
content:
application/json:
schema:
$ref: '#/components/schemas/SingleTranslationResponse'
/api/translate/stream:
post:
summary: ストリーミング翻訳(SSE)
description: |
Server-Sent Events(SSE)を使用してリアルタイムに翻訳結果をストリーミングします。
同時接続数はユーザーあたり最大3本に制限されます。
operationId: translateStream
x-audience: public
x-auth: cookie
tags:
- Translation
security:
- CookieAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TranslationRequest'
responses:
'200':
description: SSEストリーミング翻訳レスポンス
content:
text/event-stream:
schema:
type: string
description: |
Server-Sent Eventsストリーム。
各イベントはJSON形式で翻訳の進捗・結果を含む。
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/health:
get:
summary: ヘルスチェック
description: システムの健全性を確認します。
operationId: healthCheck
x-audience: internal
x-auth: none
tags:
- Health
security: []
responses:
'200':
description: システムは正常に動作しています
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: サービスが利用できません
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/stripe/webhook:
post:
summary: Stripe Webhook受信
description: |
Stripeからのイベント通知を受信し、処理します。
署名検証を必須とし、べき等性を保証します。
operationId: handleStripeWebhook
x-audience: internal
x-auth: signature
tags:
- Stripe
security: [] # Webhookは署名ヘッダーで検証するためBearerトークン不要
parameters:
- in: header
name: stripe-signature
required: true
schema:
type: string
description: Stripe署名ヘッダー
requestBody:
required: true
content:
application/json:
schema:
type: object
description: Stripeイベントペイロード
responses:
'200':
description: Webhook処理成功
content:
application/json:
schema:
type: object
properties:
received:
type: boolean
example: true
'400':
description: 無効な署名または不正なペイロード
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
# NOTE: Customer Portal Session作成はServer Action(src/app/actions/payment.ts)で実装。
# API Routeとしては存在しない。
# ============================================================================
# Preview API エンドポイント(ハイブリッドプレビュー機能)
# ============================================================================
/api/preview/start:
post:
summary: プレビュージョブ開始
description: |
PPTXファイルのプレビュージョブを開始します。
Python service が所有者確認済みの Storage bytes と実際の converter identity を使ってジョブを解決し、
新規作成時は同じ Python request 内で PDF を生成します。
同一 file、PPTX bytes の SHA-256、converter identity の active job は再利用されます。
同一 identity の completed と completed_with_errors はどちらも再利用されます。
completed_with_errors の再利用は既存の失敗ページと retry count を維持します。
異なる identity の active job がある場合は 409 です。
Python が実際の converter identity を確認できない場合は、job を作成せず 503 です。
operationId: startPreviewJob
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewStartRequest'
responses:
'200':
description: ジョブ開始成功(または既存ジョブを返却)
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewStartResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: 別 identity のプレビュージョブが既に実行中
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
$ref: '#/components/responses/TooManyRequests'
'503':
description: Python converter identity または依存サービスを利用できない
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/status:
get:
summary: プレビュージョブステータス取得
description: |
プレビュージョブの状態とページ一覧を返します。
ポーリングで進捗確認する用途で使用します。
operationId: getPreviewStatus
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
parameters:
- name: jobId
in: query
required: true
description: プレビュージョブID
schema:
type: string
format: uuid
responses:
'200':
description: ステータス取得成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewStatusResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/pdf-url:
get:
summary: PDF署名URL取得
description: |
PDFの一時的な閲覧URLを生成して返します。
URLは1時間有効です。
operationId: getPreviewPdfUrl
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
parameters:
- name: jobId
in: query
required: true
description: プレビュージョブID
schema:
type: string
format: uuid
responses:
'200':
description: URL取得成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewSignedUrlResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: ジョブが見つからない、またはPDFが未生成
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/thumb-url:
get:
summary: サムネイル署名URL取得
description: |
指定ページのサムネイル一時閲覧URLを生成して返します。
URLは1時間有効です。
operationId: getPreviewThumbUrl
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
parameters:
- name: jobId
in: query
required: true
description: プレビュージョブID
schema:
type: string
format: uuid
- name: page
in: query
required: true
description: ページインデックス(0始まり)
schema:
type: integer
minimum: 0
responses:
'200':
description: URL取得成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewSignedUrlResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: ジョブが見つからない、またはサムネイルが未生成
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/thumb-urls:
get:
summary: サムネイル署名URL一括取得
description: |
指定ジョブの done ページのサムネイル署名URLをバッチで返す。
個別 /api/preview/thumb-url の N+1 問題を解消する。
URL は1時間有効。
operationId: getPreviewThumbUrls
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
parameters:
- name: jobId
in: query
required: true
description: プレビュージョブID
schema:
type: string
format: uuid
responses:
'200':
description: 一括URL取得成功(page_index → signed URL のマップ)
content:
application/json:
schema:
type: object
required:
- urls
properties:
urls:
type: object
additionalProperties:
type:
- string
- 'null'
description: 署名済み URL(thumb 未生成の場合は null)
description: page_index をキー、署名URLを値とするマップ
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/thumbs-start:
post:
summary: サムネイル生成開始
description: |
Cloud Runにサムネイル生成を依頼します。
リースロックにより多重起動は防止されます。
operationId: startPreviewThumbs
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsStartRequest'
responses:
'200':
description: サムネイル生成開始成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsStartResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: サービス未設定(PYTHON_SERVICE_URLが未設定)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/preview/thumbs-retry:
post:
summary: 失敗ページ一括再生成
description: |
failed状態の全ページを再生成します。
operationId: retryPreviewThumbs
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsRetryRequest'
responses:
'200':
description: 再生成開始成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsRetryResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: サービス未設定
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/api/preview/thumbs-retry-page:
post:
summary: 単一ページ再生成
description: |
指定ページのサムネイルを再生成します。
operationId: retryPreviewThumbPage
x-audience: public
x-auth: cookie
tags:
- Preview
security:
- CookieAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsRetryPageRequest'
responses:
'200':
description: 再生成成功
content:
application/json:
schema:
$ref: '#/components/schemas/PreviewThumbsRetryPageResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
description: サービス未設定
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
# ============================================================================
# Auth エンドポイント
# ============================================================================
/api/auth/callback:
get:
summary: OAuth/Magic Linkコールバック
description: |
Supabase Auth の PKCE フロー完了後にリダイレクトされるコールバック。
認証コードをセッションに交換し、next パラメータへリダイレクトする。
operationId: authCallback
x-audience: public
x-auth: none
tags:
- Auth
security: []
parameters:
- name: code
in: query
description: Supabase Auth が発行する認証コード
schema:
type: string
- name: next
in: query
description: 認証後のリダイレクト先パス(sanitizeNextPath で検証)
schema:
type: string
default: /dashboard
responses:
'307':
description: |
認証成功時は next へリダイレクト。
失敗時(コード無効・未提供)は /login?error=auth_callback_error へリダイレクト。
Rate Limit超過時は /login?error=rate_limited へリダイレクト。
/api/auth/csrf:
get:
summary: CSRFトークン取得
description: |
フォーム送信前にCSRFトークンを取得するエンドポイント。
Rate Limit 適用。キャッシュ無効化ヘッダー付き。
operationId: getCsrfToken
x-audience: public
x-auth: none
tags:
- Auth
security: []
responses:
'200':
description: トークン取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
required:
- data
properties:
data:
type: object
required:
- csrfToken
properties:
csrfToken:
type: string
description: CSRFトークン
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/auth/session:
get:
summary: セッション確認
description: |
現在のユーザーセッションを検証し、ユーザー情報を返す。
Origin 検証 + Rate Limit 適用。
operationId: getSession
x-audience: public
x-auth: cookie
tags:
- Auth
security:
- CookieAuth: []
responses:
'200':
description: セッション有効
content:
application/json:
schema:
type: object
required:
- success
- data
properties:
success:
type: boolean
data:
type: object
required:
- user
- session
properties:
user:
type: object
required:
- id
additionalProperties: false
properties:
id:
type: string
format: uuid
email:
type: string
format: email
session:
type: object
required:
- user
properties:
user:
type: object
required:
- id
additionalProperties: false
properties:
id:
type: string
format: uuid
email:
type: string
format: email
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
/api/auth/logout:
post:
summary: ログアウト
description: |
Supabase Auth からサインアウトし、Clear-Site-Data ヘッダーで
Cookie/Storage を一括クリアする。Origin 検証 + Rate Limit 適用。
operationId: logout
x-audience: public
x-auth: cookie
tags:
- Auth
security:
- CookieAuth: []
responses:
'200':
description: ログアウト成功
headers:
Clear-Site-Data:
description: Cookie/Storage クリア指示
schema:
type: string
content:
application/json:
schema:
type: object
required:
- success
- data
properties:
success:
type: boolean
data:
type: object
properties:
message:
type: string
redirectTo:
type: string
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
/api/auth/is-admin:
get:
summary: 管理者判定
description: |
現在のユーザーが管理者かどうかを profiles テーブルの role で判定する。
未認証の場合は isAdmin: false を返す(エラーではない)。
operationId: isAdmin
x-audience: public
x-auth: cookie
tags:
- Auth
security:
- CookieAuth: []
responses:
'200':
description: 判定結果
content:
application/json:
schema:
type: object
required:
- success
- data
properties:
success:
type: boolean
data:
type: object
required:
- isAdmin
properties:
isAdmin:
type: boolean
reason:
type: string
enum: [profiles, none, unauthenticated, error]
hasProfile:
type: boolean
email:
type: string
description: マスク済みメールアドレス
'429':
$ref: '#/components/responses/TooManyRequests'
# ============================================================================
# Files 追加エンドポイント
# ============================================================================
/api/files/{id}/download:
get:
summary: ファイルダウンロード
description: |
元ファイルまたは翻訳済みファイルをダウンロードする。
ファイル名を指定した短期署名URLを生成し、Storageへ一時リダイレクトする。
アプリケーションサーバーはファイル本体をバッファリングしない。
FILE_DOWNLOAD監査イベントはStorage取得完了ではなく署名URL発行時に記録する。
Rate Limit 適用(ダウンロード専用プリセット)。
operationId: downloadFile
x-audience: public
x-auth: cookie
tags:
- Files
security:
- CookieAuth: []
parameters:
- name: id
in: path
required: true
description: ファイルID
schema:
type: string
format: uuid
- name: type
in: query
description: ダウンロード種別
schema:
type: string
enum: [original, translated]
default: original
responses:
'302':
description: Supabase Storageの短期署名URLへリダイレクト
headers:
Location:
required: true
description: downloadファイル名を含む短期署名URL
schema:
type: string
format: uri
X-Request-Id:
description: リクエスト追跡ID
schema:
type: string
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
# ============================================================================
# Usage エンドポイント
# ============================================================================
/api/usage/check:
get:
summary: 使用量チェック
description: |
ユーザーの月間使用量と残り翻訳可能ファイル数を返す。
Origin 検証適用。
operationId: checkUsage
x-audience: public
x-auth: cookie
tags:
- Files
security:
- CookieAuth: []
responses:
'200':
description: 使用量情報
content:
application/json:
schema:
$ref: '#/components/schemas/UsageCheckResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ============================================================================
# Error Report エンドポイント
# ============================================================================
/api/error-report:
post:
summary: クライアントエラーレポート
description: |
クライアント側で発生したエラーをサーバーに報告する。
error-boundary-wrapper.tsx から自動送信される。
CSRF + Origin 検証 + Rate Limit 適用。匿名ユーザーも受理可能。
operationId: reportError
x-audience: public
x-auth: none
tags:
- Health
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorReportRequest'
responses:
'200':
description: レポート受信成功
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
message:
type: string
requestId:
type: string
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
# ============================================================================
# Internal Health エンドポイント
# ============================================================================
# ============================================================================
# Admin API エンドポイント(withAdmin*Handler 経由・admin role 必須)
# ============================================================================
# NOTE: /api/admin/* は順次 OpenAPI に追記中(#1100 / #1105 follow-up)。
# 本セクションは Phase A: GET 系の登録から開始。
/api/admin/overview:
get:
summary: 管理者ダッシュボード概要
description: |
管理者向けダッシュボードに表示する集計データを返す。
ユーザー集計・ファイル集計・直近のアクティビティログ・当月の利用統計を一括取得する。
Service role client を使用するため、`withAdminGetHandler` で admin role を必須とする。
operationId: getAdminOverview
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 集計データ取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
$ref: '#/components/schemas/AdminOverviewResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/analytics:
get:
summary: 翻訳・利用分析データ
description: |
翻訳パイプラインの分析データを返す。
クエリパラメータで取得対象を切り替える: `summary` / `failure` / `performance` / `language` / `retry` / `timeseries` / `translation`。
SSOT: `src/lib/analytics/queries.ts` および `src/lib/admin/translation-analytics.ts`。
レスポンス shape は type ごとに異なるため、本仕様では汎用 object として表現する。
operationId: getAdminAnalytics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: query
name: type
schema:
type: string
enum: [summary, failure, performance, language, retry, timeseries, translation]
default: summary
- in: query
name: startDate
schema:
type: string
format: date-time
description: ISO 8601 形式(snake_case の `start_date` も受理)
- in: query
name: endDate
schema:
type: string
format: date-time
description: ISO 8601 形式(snake_case の `end_date` も受理)
- in: query
name: granularity
schema:
type: string
enum: [hour, day, week]
description: timeseries 取得時のみ有効
responses:
'200':
description: 分析データ取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
description: type パラメータごとに異なる集計結果
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/health:
get:
summary: 管理者用ヘルスメトリクス
description: |
エラー率・応答時間・API 成功率などのシステムヘルスメトリクスを返す。
SSOT: `src/lib/admin/health-monitoring.ts`。
`/api/health` (public uptime monitor) や `/api/internal/health` (deep check) とは別系統。
operationId: getAdminHealthMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: query
name: start_date
schema:
type: string
format: date-time
- in: query
name: end_date
schema:
type: string
format: date-time
responses:
'200':
description: ヘルスメトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/operations:
get:
summary: オペレーションメトリクス
description: |
失敗率・p50/p95 レイテンシ・リトライ分布などのオペレーションメトリクスを返す。
SSOT: `src/lib/analytics/operations-metrics.ts`。
operationId: getAdminOperationsMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: query
name: days
schema:
type: integer
default: 30
minimum: 1
description: 集計対象の過去日数
responses:
'200':
description: オペレーションメトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/quality:
get:
summary: 翻訳品質メトリクス
description: |
ダウンロード率・再翻訳率・編集率などの品質指標を返す。
SSOT: `src/lib/analytics/quality-metrics.ts`。
operationId: getAdminQualityMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: query
name: days
schema:
type: integer
minimum: 1
maximum: 365
default: 30
description: 集計対象とする過去日数
responses:
'200':
description: 品質メトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
$ref: '#/components/schemas/QualityMetrics'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/revenue:
get:
summary: 収益メトリクス
description: |
MRR / ARR / 解約率 / 支払い失敗 / 返金などの収益指標を返す。
Stripe データと内部 subscription state を集計。
operationId: getAdminRevenueMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 収益メトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/costs:
get:
summary: コスト監視メトリクス
description: |
Claude API 使用量・Supabase Storage 使用量を集計する。
SSOT: `src/lib/admin/cost-monitoring.ts`。
operationId: getAdminCostMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: コストメトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/abuse:
get:
summary: 不正利用検知
description: |
異常利用パターン(短時間大量アップロード等)を検出する。
SSOT: `src/lib/admin/abuse-detection.ts`。
operationId: getAdminAbuseDetection
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 検知結果取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/security:
get:
summary: セキュリティメトリクス
description: |
Rate Limit 統計・認証エラー・異常検知・スタックファイル検知などを集計する。
SSOT: `src/lib/analytics/anomaly-detection.ts`, `src/lib/analytics/stuck-detection.ts`。
operationId: getAdminSecurityMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: セキュリティメトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/users:
get:
summary: ユーザー一覧(管理者用)
description: |
管理者向けユーザー一覧を返す。フィルタ・ソート・ページネーション可。
SSOT: `src/lib/admin/users.ts`。
operationId: getAdminUsers
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: query
name: search
schema:
type: string
description: ユーザー名 / email 部分一致
- in: query
name: role
schema:
type: string
enum: [user, admin]
- in: query
name: is_blocked
schema:
type: string
enum: ["true", "false"]
description: ブロック状態フィルタ(boolean を文字列で渡す)
- in: query
name: has_subscription
schema:
type: string
enum: ["true", "false"]
- in: query
name: plan_name
schema:
type: string
enum: [free, standard, pro]
- in: query
name: sort_by
schema:
type: string
default: created_at
- in: query
name: sort_order
schema:
type: string
enum: [asc, desc]
default: desc
- in: query
name: limit
schema:
type: integer
minimum: 1
maximum: 200
default: 50
- in: query
name: offset
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: ユーザー一覧取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/users/{id}:
get:
summary: ユーザー詳細(管理者用)
description: 指定 ID のユーザー詳細・関連 metadata を返す。
operationId: getAdminUserDetail
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
format: uuid
responses:
'200':
description: ユーザー詳細取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/users/{id}/block:
post:
summary: ユーザーブロック切替
description: |
指定 ID のユーザーのブロック状態を変更する。
body の `is_blocked` で true/false を切替。
operationId: postAdminUserBlock
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- is_blocked
properties:
is_blocked:
type: boolean
responses:
'200':
description: ブロック状態変更成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/users/{id}/subscription:
post:
summary: ユーザーサブスクリプション変更
description: |
指定 ID のユーザーのプランを変更する。Stripe との同期は内部で実施。
operationId: postAdminUserSubscription
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
format: uuid
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- plan_name
properties:
plan_name:
type: string
enum: [free, standard, pro]
responses:
'200':
description: プラン変更成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/recover-stuck:
get:
summary: スタックファイル一覧
description: |
翻訳が長時間進まないファイルを一覧で返す(運用復旧支援)。
SSOT: `src/lib/analytics/stuck-detection.ts`。
operationId: getAdminRecoverStuck
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: スタックファイル一覧取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: スタックファイル復旧実行
description: |
thresholdMs を超えて停止しているファイルの翻訳を再キックする。
body 省略時は default の閾値で実行する。
operationId: postAdminRecoverStuck
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
thresholdMs:
type: integer
minimum: 1
description: スタック判定の閾値(ミリ秒)。省略時は default を使用
responses:
'200':
description: 復旧処理実行成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/admin/metrics:
get:
summary: 監視メトリクス
description: |
直近1時間の翻訳実行イベント成功/失敗率とファイル数を返す。
翻訳実行イベントが0件の場合、失敗率は未計測として null を返す。
5 分間のキャッシュ付き。
operationId: getAdminMonitoringMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: メトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
required: [metrics, cached]
properties:
metrics:
type: object
required:
- cachedAt
- failedTranslationExecutionsLastHour
- totalFilesLastHour
- totalTranslationExecutionsLastHour
- translationFailureRate
properties:
cachedAt:
type: string
format: date-time
failedTranslationExecutionsLastHour:
type: integer
minimum: 0
totalFilesLastHour:
type: integer
minimum: 0
totalTranslationExecutionsLastHour:
type: integer
minimum: 0
translationFailureRate:
type: [string, "null"]
description: 翻訳実行が0件の場合は未計測のnull。
cached:
type: boolean
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
# ============================================================================
# Internal / 観測系(#1105 Phase B)
# ============================================================================
/api/health/db:
get:
summary: DB ヘルスチェック(運用者向け)
description: |
Postgres / Supabase の実接続チェックを返す。
本番では `Authorization: Bearer ${HEALTH_CHECK_SECRET}` 必須(未提示時は admin のみ許可)。
本番でトークンも admin もない場合は 403 (fail-closed)。
operationId: getHealthDb
x-audience: internal
x-auth: bearer_token
tags:
- Health
security:
- HealthCheckSecretAuth: []
responses:
'200':
description: DB 正常
content:
application/json:
schema:
type: object
additionalProperties: true
'403':
description: 未認証または HEALTH_CHECK_SECRET 未設定(fail-closed)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: DB 異常
content:
application/json:
schema:
type: object
additionalProperties: true
/api/health/auth:
get:
summary: 認証システムヘルスチェック(運用者向け)
description: |
認証コンポーネント(Supabase Auth, JWT 等)の設定確認エンドポイント。
本番では `Authorization: Bearer ${HEALTH_CHECK_SECRET}` または admin 必須。
operationId: getHealthAuth
x-audience: internal
x-auth: bearer_token
tags:
- Health
security:
- HealthCheckSecretAuth: []
responses:
'200':
description: 認証システム正常
content:
application/json:
schema:
type: object
additionalProperties: true
'403':
description: 未認証
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: 認証システム異常
content:
application/json:
schema:
type: object
additionalProperties: true
/api/security/stats:
get:
summary: セキュリティ統計(管理者用)
description: |
Rate Limit / IP block / 異常検知などのセキュリティ統計を返す。
SSOT: `src/lib/security/security-metrics.ts`。
operationId: getSecurityStats
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 統計取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/security/token-stats:
get:
summary: トークン統計(管理者用)
description: |
JWT / refresh token の発行・失効・回転状況を集計する。
SSOT: `src/lib/security/jti-tracker.ts`, `token-rotation.ts`。
operationId: getSecurityTokenStats
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: トークン統計取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: トークン統計クリア
description: 管理者向け運用操作。トークン統計のクリア・リセット。
operationId: postSecurityTokenStats
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 操作成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/translate/metrics:
get:
summary: 翻訳メトリクス(管理者用)
description: |
詳細な翻訳性能メトリクス収集は停止中。全variantで collectionStatus=paused、
measured=false とし、測定値は null を返す。0 を健全な実測値として扱わない。
public ユーザーには公開しない管理者専用エンドポイント。
operationId: getTranslateMetrics
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 翻訳メトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
oneOf:
- type: object
required: [type, fileId, collectionStatus, measured, metrics]
properties:
type:
type: string
const: file
fileId:
type: string
collectionStatus:
type: string
const: paused
measured:
type: boolean
const: false
metrics:
type: "null"
- type: object
required: [type, period, collectionStatus, measured, metrics]
properties:
type:
type: string
const: realtime
period:
type: string
const: 1h
collectionStatus:
type: string
const: paused
measured:
type: boolean
const: false
metrics:
type: "null"
- type: object
required:
- type
- period
- collectionStatus
- measured
- totals
- averages
- dailyMetrics
properties:
type:
type: string
const: summary
period:
type: string
description: Requested day count followed by d.
collectionStatus:
type: string
const: paused
measured:
type: boolean
const: false
totals:
type: "null"
averages:
type: "null"
dailyMetrics:
type: "null"
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/metrics/cache:
get:
summary: 翻訳キャッシュメトリクス(管理者用)
description: |
翻訳キャッシュ(RPC v2)のヒット率・命中件数・失効件数等を返す。
operationId: getMetricsCache
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: キャッシュメトリクス取得成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: 翻訳キャッシュ操作(管理者用)
description: 管理者向けキャッシュ操作(パージ等)。
operationId: postMetricsCache
x-audience: admin
x-auth: admin_session
tags:
- Admin
security:
- CookieAuth: []
responses:
'200':
description: 操作成功
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/ApiSuccessEnvelope'
- type: object
properties:
data:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/preview/recovery:
get:
summary: プレビュー復旧対象一覧(cron / 監視向け)
description: |
失敗 / スタックしたプレビュージョブのリストを返す。
staging / production は Cloud Scheduler OIDC(`SCHEDULER_SA_EMAILS` allowlist)必須。
local / test は OIDC または `x-cron-secret` で許可。
詳細: `docs/preview-system.md`。
operationId: getPreviewRecovery
x-audience: internal
x-auth: oidc
tags:
- Preview
security: []
responses:
'200':
description: 対象ジョブ一覧取得成功
content:
application/json:
schema:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
post:
summary: プレビュー復旧バッチ実行(cron)
description: |
失敗 / スタックジョブの再キックを実行する。Cloud Scheduler から定期実行される想定。
operationId: postPreviewRecovery
x-audience: internal
x-auth: oidc
tags:
- Preview
security: []
responses:
'200':
description: 復旧処理実行成功
content:
application/json:
schema:
type: object
additionalProperties: true
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
/api/internal/health:
get:
summary: 内部ヘルスチェック(認証必須)
description: |
DB/Storage の実接続チェックを含む詳細なヘルスチェック。
Service Role Key を使用するため、Bearer token(HEALTH_CHECK_SECRET)で保護。
用途: 本番環境の深いヘルスモニタリング(Vercel cron / 内部監視)。
operationId: internalHealthCheck
x-audience: internal
x-auth: bearer_token
tags:
- Health
security:
- HealthCheckSecretAuth: []
responses:
'200':
description: 全コンポーネント正常
content:
application/json:
schema:
$ref: '#/components/schemas/InternalHealthResponse'
'403':
description: 未認証または HEALTH_CHECK_SECRET 未設定(fail-closed)
content:
application/json:
schema:
type: object
properties:
error:
type: string
'503':
description: 一部コンポーネント異常
content:
application/json:
schema:
$ref: '#/components/schemas/InternalHealthResponse'
components:
securitySchemes:
# NOTE (#1089 / #1094 follow-up): Cookie session を SSOT として CookieAuth に統一。
# 旧 BearerAuth 記述は 18 endpoint 全てを CookieAuth に移行済み。
# 新規エンドポイントは必ず CookieAuth を使用すること。
CookieAuth:
type: apiKey
in: cookie
name: sb-access-token
description: |
Supabase Auth の Cookie session(HttpOnly + Secure + SameSite=Lax)。
実装上の cookie 名は project ref に依存する
(例: `sb-<project-ref>-auth-token`) が、論理的に本スキームで表現する。
HealthCheckSecretAuth:
type: http
scheme: bearer
description: HEALTH_CHECK_SECRET 環境変数による内部ヘルスチェック認証(Supabase JWT とは別)
parameters:
TranslationJobId:
name: jobId
in: path
required: true
schema: { type: string, format: uuid }
schemas:
# ============================================================================
# 基本型定義
# ============================================================================
TranslationJobItem:
type: object
additionalProperties: false
required: [item_key, original_text]
properties:
item_key: { type: string, minLength: 1, maxLength: 255 }
original_text: { type: string, minLength: 1, maxLength: 20000 }
slide_number: { type: integer, minimum: 0 }
element_index: { type: integer, minimum: 0 }
TranslationJobOwnedManifest:
description: Server-owned manifest derived from the file extracted_data. Create requests do not accept an items body; this schema documents the execution cap.
type: array
minItems: 1
maxItems: 5000
items:
$ref: '#/components/schemas/TranslationJobItem'
TranslationJobCreateRequest:
type: object
additionalProperties: false
required: [fileId, targetLanguage]
properties:
fileId: { type: string, format: uuid }
targetLanguage: { type: string, pattern: '^[a-z]{2}(-[A-Z]{2})?$' }
sourceLanguage: { type: string, pattern: '^[a-z]{2}(-[A-Z]{2})?$' }
options:
type: object
additionalProperties: false
properties:
customInstruction: { type: string, maxLength: 100000 }
glossary:
type: object
additionalProperties: { type: string, maxLength: 500 }
includeSpeakerNotes: { type: boolean }
qualityTier: { type: string, enum: [standard, high] }
sourceLang: { type: string, pattern: '^[a-z]{2}(-[A-Z]{2})?$' }
style: { type: string, enum: [standard, business, technical, casual] }
TranslationJobResponse:
type: object
additionalProperties: false
required: [id, fileId, status, targetLanguage, totalItems, completedItems, failedItems, pagesTranslated, errorCode, revisionId, createdAt, updatedAt, completedAt, cancelledAt]
properties:
id: { type: string, format: uuid }
fileId: { type: string, format: uuid }
status: { type: string, enum: [queued, running, ready_to_finalize, finalizing, completed, completed_with_errors, failed, cancelled] }
targetLanguage: { type: string }
totalItems: { type: integer, minimum: 0 }
completedItems: { type: integer, minimum: 0 }
failedItems: { type: integer, minimum: 0 }
pagesTranslated: { type: integer, minimum: 0 }
errorCode: { type: [string, 'null'] }
revisionId: { type: [string, 'null'], format: uuid }
createdAt: { type: string, format: date-time }
updatedAt: { type: string, format: date-time }
completedAt: { type: [string, 'null'], format: date-time }
cancelledAt: { type: [string, 'null'], format: date-time }
TranslationJobTerminalNoticeClaim:
oneOf:
- type: object
additionalProperties: false
required: [claimed, status]
properties:
claimed: { const: false }
status: { type: 'null' }
- type: object
additionalProperties: false
required: [claimed, status]
properties:
claimed: { const: true }
status: { type: string, enum: [completed, completed_with_errors, failed, cancelled] }
QualityMetrics:
type: object
additionalProperties: false
required:
- cohortBasis
- downloadUrlIssuanceRate
- editCohortBasis
- retranslationRate
- editFileRate
- editElementRate
- editObservationPeriod
- editReasonCounts
- totalTranslations
- totalDownloadUrlsIssued
- period
properties:
cohortBasis:
type: string
enum: [file_created_at]
description: downloadUrlIssuanceRateとtotalTranslationsのcompletedファイルコホートを期間抽出する時刻列。現行はファイル作成日時
downloadUrlIssuanceRate:
type: number
minimum: 0
maximum: 100
description: 期間内作成かつ現在completedのファイルのうち、同期間内に1回以上署名ダウンロードURLが発行されたファイルの割合。Storage取得完了率ではない
editCohortBasis:
type: string
enum: [file_completed_at]
description: 編集機会の開始を表すファイル翻訳完了日時を編集率コホートの基準とする
retranslationRate:
$ref: '#/components/schemas/RetranslationRateMeasurement'
description: 翻訳operation種別の計測開始前後を明示する再翻訳率
editFileRate:
$ref: '#/components/schemas/EditRateMeasurement'
description: 編集されたファイル数を翻訳完了ファイル数で割った割合
editElementRate:
$ref: '#/components/schemas/EditRateMeasurement'
description: 編集された翻訳要素数を翻訳完了要素数で割った割合
editObservationPeriod:
$ref: '#/components/schemas/EditObservationPeriod'
editReasonCounts:
$ref: '#/components/schemas/EditReasonCounts'
totalTranslations:
type: integer
minimum: 0
description: 期間内に作成され、現在completedのファイル数
totalDownloadUrlsIssued:
type: integer
minimum: 0
description: 期間内の署名ダウンロードURL発行イベント総数(同一ファイルの重複を含む)。Storage取得完了数ではない
period:
type: object
additionalProperties: false
required: [start, end]
properties:
start:
type: string
format: date-time
end:
type: string
format: date-time
EditRateMeasurement:
description: 編集履歴計測の開始前後を明示する測定値
oneOf:
- type: object
additionalProperties: false
required: [status, value, reason, numerator, denominator]
properties:
status:
type: string
enum: [available]
value:
type: number
minimum: 0
maximum: 100
reason:
type: "null"
numerator:
type: integer
minimum: 0
denominator:
type: integer
minimum: 1
- type: object
additionalProperties: false
required: [status, value, reason]
properties:
status:
type: string
enum: [unavailable]
value:
type: "null"
reason:
type: string
enum: [translation_edit_tracking_not_started, no_eligible_cohort]
EditObservationPeriod:
type: object
additionalProperties: false
required: [requestedStart, effectiveStart, end, trackingStartedAt, coverageStatus]
properties:
requestedStart:
type: string
format: date-time
effectiveStart:
type: [string, "null"]
format: date-time
end:
type: string
format: date-time
trackingStartedAt:
type: [string, "null"]
format: date-time
coverageStatus:
oneOf:
- type: string
enum: [full, tracking_started_during_period, retention_truncated]
- type: "null"
EditReasonCounts:
type: object
additionalProperties: false
required: [manual_edit, ai_refine_accept, overflow_shorten_accept, unclassified]
properties:
manual_edit:
type: integer
minimum: 0
ai_refine_accept:
type: integer
minimum: 0
overflow_shorten_accept:
type: integer
minimum: 0
unclassified:
type: integer
minimum: 0
RetranslationRateMeasurement:
description: 翻訳operation種別の計測開始前後を明示する測定値
oneOf:
- type: object
additionalProperties: false
required: [status, value, reason]
properties:
status:
type: string
enum: [available]
value:
type: number
minimum: 0
maximum: 100
reason:
type: "null"
- type: object
additionalProperties: false
required: [status, value, reason]
properties:
status:
type: string
enum: [unavailable]
value:
type: "null"
reason:
type: string
enum: [translation_operation_tracking_not_started]
TargetLanguage:
type: string
description: "翻訳対象言語コード(BCP 47)。SSOT: config/languages.yaml"
enum:
- ja
- en
- zh
- zh-TW
- ko
- es
- fr
- de
- it
- pt
- ru
- ar
- hi
- th
- vi
# ============================================================================
# 翻訳関連スキーマ
# ============================================================================
TextToTranslate:
type: object
description: 翻訳リクエスト用のテキスト
required:
- id
- text
properties:
id:
type: string
description: テキスト要素のID
text:
type: string
description: 翻訳するテキスト
context:
type: string
description: テーブル等のコンテキスト情報
TranslatedTextResult:
type: object
description: 翻訳結果
required:
- id
- original
- translated
properties:
id:
type: string
description: テキスト要素のID
original:
type: string
description: 元のテキスト
translated:
type: string
description: 翻訳されたテキスト
confidence:
type: number
description: 翻訳の信頼度(0-1)
minimum: 0
maximum: 1
SingleTranslationRequest:
type: object
description: 単一テキスト翻訳リクエスト(/api/translate/single 用)
required:
- fileId
- text
- textId
- slideIndex
- targetLanguage
properties:
fileId:
type: string
format: uuid
description: 翻訳対象ファイルのID
text:
type: string
description: 翻訳するテキスト
textId:
type: string
description: テキスト要素のID
slideIndex:
type: integer
minimum: 0
description: スライドインデックス(0始まり)
targetLanguage:
$ref: '#/components/schemas/TargetLanguage'
sourceLanguage:
type: string
description: "ソース言語コード(オプション)"
priority:
type: string
enum: [INTERACTIVE, BACKGROUND, BATCH]
description: 翻訳優先度
SingleTranslationResponse:
type: object
description: 単一テキスト翻訳レスポンス
required:
- success
properties:
success:
type: boolean
translatedText:
type: string
description: 翻訳結果テキスト
fromCache:
type: boolean
description: キャッシュから取得したかどうか
errorCode:
type: string
description: エラーコード(エラー時)
retryAfter:
type: integer
minimum: 0
description: 再試行可能になるまでの秒数(エラー時)
TranslationRequest:
type: object
description: ストリーミング翻訳リクエスト(/api/translate/stream 用)
required:
- texts
- targetLanguage
properties:
texts:
type: array
description: 翻訳するテキストの配列
items:
$ref: '#/components/schemas/TextToTranslate'
targetLanguage:
$ref: '#/components/schemas/TargetLanguage'
sourceLanguage:
type: string
description: "ソース言語コード(オプション、自動検出の場合は \"auto\")"
# ============================================================================
# API リクエスト/レスポンススキーマ
# ============================================================================
SuccessResponse:
type: object
description: 成功レスポンス
required:
- success
properties:
success:
type: boolean
example: true
message:
type: string
description: メッセージ
HealthResponse:
type: object
description: ヘルスチェックレスポンス
required:
- status
properties:
status:
type: string
enum:
- ok
- error
description: システムの状態
timestamp:
type: string
format: date-time
description: チェック時刻
version:
type: string
description: APIバージョン
# ============================================================================
# Preview API スキーマ
# ============================================================================
PreviewJobStatus:
type: string
description: プレビュージョブの状態
enum:
- queued
- pdf_generating
- pdf_ready
- thumbs_running
- completed
- completed_with_errors
- failed
PreviewPageStatus:
type: string
description: プレビューページの状態
enum:
- pending
- done
- failed
PreviewPage:
type: object
description: プレビューページ情報
required:
- page_index
- status
properties:
page_index:
type: integer
description: ページインデックス(0始まり)
minimum: 0
status:
$ref: '#/components/schemas/PreviewPageStatus'
width:
type: integer
description: ページ幅(ピクセル)
height:
type: integer
description: ページ高さ(ピクセル)
thumb_path:
type: string
description: サムネイルのStorage内パス
PreviewStartRequest:
type: object
description: プレビュージョブ開始リクエスト
required:
- fileId
properties:
fileId:
type: string
format: uuid
description: 対象ファイルのID
PreviewStartResponse:
type: object
description: プレビュージョブ開始レスポンス
required:
- jobId
properties:
jobId:
type: string
format: uuid
description: プレビュージョブID
existing:
type: boolean
description: 既存ジョブを返却した場合true
PreviewStatusResponse:
type: object
description: プレビュージョブステータスレスポンス
required:
- status
properties:
status:
$ref: '#/components/schemas/PreviewJobStatus'
totalPages:
type: integer
description: 総ページ数
minimum: 0
thumbsDone:
type: integer
description: サムネイル生成完了数
minimum: 0
thumbsFailed:
type: integer
description: サムネイル生成失敗数
minimum: 0
pdfPath:
type: string
description: PDFのStorage内パス
pages:
type: array
description: ページ情報の配列
items:
$ref: '#/components/schemas/PreviewPage'
error:
type: string
description: エラーメッセージ(失敗時)
PreviewSignedUrlResponse:
type: object
description: 署名付きURL取得レスポンス
required:
- url
properties:
url:
type: string
format: uri
description: 署名付きURL(1時間有効)
PreviewThumbsStartRequest:
type: object
description: サムネイル生成開始リクエスト
required:
- jobId
properties:
jobId:
type: string
format: uuid
description: プレビュージョブID
PreviewThumbsStartResponse:
type: object
description: サムネイル生成開始レスポンス
properties:
success:
type: boolean
description: 処理成功フラグ
message:
type: string
description: メッセージ
PreviewThumbsRetryRequest:
type: object
description: 失敗ページ一括再生成リクエスト
required:
- jobId
properties:
jobId:
type: string
format: uuid
description: プレビュージョブID
PreviewThumbsRetryResponse:
type: object
description: 失敗ページ一括再生成レスポンス
properties:
retriedCount:
type: integer
description: 再生成を試みたページ数
minimum: 0
message:
type: string
description: メッセージ
PreviewThumbsRetryPageRequest:
type: object
description: 単一ページ再生成リクエスト
required:
- jobId
- pageIndex
properties:
jobId:
type: string
format: uuid
description: プレビュージョブID
pageIndex:
type: integer
description: ページインデックス(0始まり)
minimum: 0
PreviewThumbsRetryPageResponse:
type: object
description: 単一ページ再生成レスポンス
properties:
success:
type: boolean
description: 処理成功フラグ
message:
type: string
description: メッセージ
# ============================================================================
# Usage / Error Report / Internal Health スキーマ
# ============================================================================
UsageCheckResponse:
type: object
description: 使用量チェックレスポンス
required:
- canTranslate
- remainingFiles
properties:
canTranslate:
type: boolean
description: 翻訳可能かどうか
remainingFiles:
type: integer
description: 残り翻訳可能ファイル数
minimum: 0
currentUsage:
type: integer
description: 今月の使用ファイル数
monthlyLimit:
type: integer
description: 月間制限ファイル数
plan:
type: string
description: 現在のプラン名
ErrorReportRequest:
type: object
description: クライアントエラーレポートリクエスト
properties:
error:
type: string
description: エラーメッセージ
message:
type: string
description: エラーメッセージ(error-boundary-wrapper 互換)
errorInfo:
type: object
properties:
componentStack:
type: string
stack:
type: string
type:
type: string
url:
type: string
stack:
type: string
description: スタックトレース(フラットペイロード互換)
url:
type: string
description: エラー発生URL(フラットペイロード互換)
userAgent:
type: string
timestamp:
type: string
InternalHealthResponse:
type: object
description: 内部ヘルスチェックレスポンス
required:
- status
- timestamp
- checks
- test_mode_enabled
properties:
status:
type: string
enum: [healthy, unhealthy]
timestamp:
type: string
format: date-time
test_mode_enabled:
type: boolean
description: |
production runtime では常に false。
true が返った場合は env 設定不備(Vercel に E2E_* が残存等)または production 判定失敗を示す。
#1128: post-deploy probe で本フィールドを監視し、true なら deploy job を fail させる。
checks:
type: object
properties:
database:
$ref: '#/components/schemas/HealthCheckResult'
storage:
$ref: '#/components/schemas/HealthCheckResult'
rpc:
$ref: '#/components/schemas/HealthCheckResult'
anthropic:
$ref: '#/components/schemas/HealthCheckResult'
stripe:
$ref: '#/components/schemas/HealthCheckResult'
HealthCheckResult:
type: object
description: 個別コンポーネントのヘルスチェック結果
required:
- status
properties:
status:
type: string
enum: [healthy, unhealthy, configured, disabled, missing, partial]
description: |
stripe の disabled は Stripe の 4 つの env が全部ない無料公開で、正常な状態。
partial は一部だけ設定された不正な状態で、unhealthy として扱う。
latency:
type: integer
description: レイテンシ(ミリ秒)
# ============================================================================
# エラーレスポンススキーマ
# ============================================================================
ErrorResponse:
type: object
description: エラーレスポンス
required:
- error
properties:
error:
type: object
required:
- type
- message
- timestamp
properties:
type:
type: string
enum:
- VALIDATION_ERROR
- AUTHENTICATION_ERROR
- AUTHORIZATION_ERROR
- NOT_FOUND
- CONFLICT
- RATE_LIMIT_ERROR
- EXTERNAL_SERVICE_ERROR
- DATABASE_ERROR
- FILE_PROCESSING_ERROR
- INTERNAL_SERVER_ERROR
description: エラータイプ
message:
type: string
description: エラーメッセージ
code:
type: string
description: エラーコード(オプション)
details:
type: object
description: エラーの詳細情報(オプション)
additionalProperties: true
timestamp:
type: string
format: date-time
description: エラー発生時刻
requestId:
type: string
format: uuid
description: リクエストID(デバッグ用)
# ============================================================================
# 共通レスポンスエンベロープ(src/lib/api/response-builder.ts と整合)
# ============================================================================
ApiSuccessEnvelope:
type: object
description: |
`createApiSuccessResponse()` が返す共通成功レスポンスエンベロープ。
個別エンドポイントは `allOf` で `data` プロパティを上書きする。
required:
- success
- status
- data
- timestamp
- requestId
properties:
success:
type: boolean
enum: [true]
status:
type: integer
description: HTTP ステータスコード
data:
description: ペイロード本体(個別エンドポイントで型を上書き)
timestamp:
type: string
format: date-time
requestId:
type: string
format: uuid
metadata:
type: object
additionalProperties: true
description: 追加メタデータ(オプション)
# ============================================================================
# Admin API スキーマ (#1100 / #1105 follow-up)
# ============================================================================
# SSOT: src/types/admin.ts (AdminOverviewResponse 等)。
# 型同期は CI 強制ではないため、admin.ts の変更時は本ファイルも更新すること。
AdminOverviewStats:
type: object
description: 管理者ダッシュボードの集計値
required:
- totalUsers
- adminUsers
- totalFiles
- completedFiles
- totalStorageUsed
- monthlyUploads
- monthlyTranslations
- successRate
properties:
totalUsers:
type: integer
adminUsers:
type: integer
totalFiles:
type: integer
completedFiles:
type: integer
totalStorageUsed:
type: integer
description: 累計ストレージ使用量(bytes)
monthlyUploads:
type: integer
description: 当月のアップロード件数
monthlyTranslations:
type: integer
description: 当月の翻訳件数
successRate:
type: number
description: 翻訳成功率 (0-100)
AdminUser:
type: object
description: 管理者ダッシュボード向けユーザー情報
required:
- id
- username
- role
- created_at
- updated_at
properties:
id:
type: string
format: uuid
username:
type: string
full_name:
type: string
role:
type: string
enum: [user, admin]
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
fileCount:
type: integer
storageUsed:
type: integer
AdminActivity:
type: object
description: アクティビティログエントリ
required:
- id
- user_id
- action
- created_at
properties:
id:
type: string
format: uuid
user_id:
type: string
format: uuid
action:
type: string
description:
type: [string, "null"]
metadata:
description: 任意の構造化メタデータ
ip_address:
type: [string, "null"]
user_agent:
type: [string, "null"]
created_at:
type: string
format: date-time
user:
type: [object, "null"]
properties:
username:
type: string
full_name:
type: string
AdminUsageStat:
type: object
description: 利用統計の日次集計
required:
- date
- uploads
- translations
- activeUsers
properties:
date:
type: string
uploads:
type: integer
translations:
type: integer
activeUsers:
type: integer
AdminOverviewResponse:
type: object
description: 管理者ダッシュボード概要レスポンス
required:
- stats
- users
- activities
- usage_stats
properties:
stats:
$ref: '#/components/schemas/AdminOverviewStats'
users:
type: array
items:
$ref: '#/components/schemas/AdminUser'
activities:
type: array
items:
$ref: '#/components/schemas/AdminActivity'
usage_stats:
type: array
items:
$ref: '#/components/schemas/AdminUsageStat'
responses:
BadRequest:
description: リクエストが不正です
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: VALIDATION_ERROR
message: ファイル情報が不足しています
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
Unauthorized:
description: 認証が必要です
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: AUTHENTICATION_ERROR
message: 認証が必要です
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
Forbidden:
description: アクセス権限がありません
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: AUTHORIZATION_ERROR
message: このファイルを削除する権限がありません
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
Conflict:
description: 現在の状態または冪等性キーと競合しています
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
NotFound:
description: リソースが見つかりません
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: NOT_FOUND
message: ファイルが見つかりません
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
TooManyRequests:
description: レート制限を超えました
headers:
Retry-After:
description: 再試行可能なまでの秒数
schema:
type: integer
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: RATE_LIMIT_ERROR
message: レート制限を超えました
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
details:
retryAfter: 60
InternalServerError:
description: サーバー内部エラー
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error:
type: INTERNAL_SERVER_ERROR
message: サーバーエラー
timestamp: '2024-01-01T00:00:00Z'
requestId: '123e4567-e89b-12d3-a456-426614174000'
エラーレスポンス
APIは標準的なHTTPステータスコードとエラーレスポンス形式を使用します。
エラーレスポンス形式
{
"error": {
"type": "ERROR_TYPE",
"message": "Error message",
"code": "ERROR_CODE",
"timestamp": "2024-01-01T00:00:00Z",
"requestId": "uuid"
}
}主なエラータイプ
VALIDATION_ERROR: リクエストのバリデーションエラー(400)AUTHENTICATION_ERROR: 認証エラー(401)AUTHORIZATION_ERROR: 認可エラー(403)NOT_FOUND: リソースが見つからない(404)RATE_LIMIT_ERROR: レート制限超過(429)INTERNAL_SERVER_ERROR: サーバー内部エラー(500)