API Documentation
REST API documentation based on OpenAPI 3.1.0 specification
API Overview
The PowerPoint Translation Tool API provides features for uploading PPTX files, extracting text, translating, and downloading.
Authentication
The API supports Bearer authentication using Supabase JWT tokens. Include Authorization: Bearer <token> in your request headers.
Base URL
Current Base URL: https://trans-ppt.work
Key Endpoints
File Upload (Server Action)
PPTX file uploads are performed via Server Actions. Files up to 25MB are supported. Direct API Route calls are not available.
extractTextFromPPTXAction (Server Action)
Extracts text elements from uploaded PPTX files via Server Action.
// Server Action (extractTextFromPPTXAction)
// クライアントコンポーネントから直接呼び出し可能
import { extractTextFromPPTXAction } from "@/app/actions/pptx";
const result = await extractTextFromPPTXAction(fileId, filePath);POST /api/translate
Translates specified text to the target language. Batch translation is also supported.
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}
Deletes the file with the specified ID.
curl -X DELETE https://trans-ppt.work/api/files/{id} \
-H "Authorization: Bearer <token>"GET /api/health
Checks system health. No authentication required.
curl https://trans-ppt.work/api/healthOpenAPI Specification
The complete OpenAPI specification can be downloaded or viewed from the links below.
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'
Error Responses
The API uses standard HTTP status codes and error response formats.
Error Response Format
{
"error": {
"type": "ERROR_TYPE",
"message": "Error message",
"code": "ERROR_CODE",
"timestamp": "2024-01-01T00:00:00Z",
"requestId": "uuid"
}
}Main Error Types
VALIDATION_ERROR: Request validation error (400)AUTHENTICATION_ERROR: Authentication error (401)AUTHORIZATION_ERROR: Authorization error (403)NOT_FOUND: Resource not found (404)RATE_LIMIT_ERROR: Rate limit exceeded (429)INTERNAL_SERVER_ERROR: Internal server error (500)