openapi: 3.0.3
info:
  title: RiskEyes V2 アクセストークンAPI
  description: |
    RiskEyes V2 アクセストークンAPI仕様書
    ## 概要
    ユーザー名とパスワードで認証し、アクセストークンとリフレッシュトークンを取得します。
    ご利用にはAPI案件を契約している必要があるため、APIを使用する前にご契約をお願いします。

    ## 留意点

    ### セキュリティ
    - **HTTPS必須**: 本APIは必ずHTTPS経由で呼び出してください
    - **認証情報の保護**: username/passwordは安全に保管し、ログに出力しないでください
    - **トークンの適切な管理**: 取得したアクセストークンは安全に保存し、第三者に漏洩しないよう注意してください

    ### トークンの有効期限
    - **アクセストークン**: 1日間有効
    - **リフレッシュトークン**: 30日間有効
    - 有効期限切れの場合は再度ログインが必要です

    ### 子クライアント認証
    - 子クライアント機能が有効なアカウントでは、`end_user_id`の指定が必要です
    - 子クライアントにパスワードが設定されている場合は、`end_user_password`が必要です

  version: 1.0.0
servers:
  - url: https://www.riskeyes.jp

paths:
  /api/v2/token:
    post:
      summary: アクセストークン・リフレッシュトークン取得
      description: ユーザー名とパスワードでログインし、アクセストークンとリフレッシュトークンを取得します
      tags:
        - Authentication
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - username
                - password
              properties:
                username:
                  type: string
                  description: ユーザー名
                  example: 'user'
                password:
                  type: string
                  description: パスワード
                  example: 'password123'
                end_user_id:
                  type: string
                  description: エンドユーザーID（子クライアント用、オプション）
                  example: 'user001'
                end_user_password:
                  type: string
                  description: エンドユーザーパスワード（子クライアント用、オプション）
                  example: 'childpassword123'
            examples:
              basic_login:
                summary: 基本ログイン
                value:
                  username: 'user'
                  password: 'password123'
              child_user_login:
                summary: 子アカウントログイン
                value:
                  username: 'user'
                  password: 'password123'
                  end_user_id: 'user001'
                  end_user_password: 'childpassword123'
      responses:
        '200':
          description: トークン取得成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  access:
                    type: string
                    description: アクセストークン
                    example: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImp0aSI6IjEyMzQ1Njc4OTAiLCJ1c2VyX2lkIjoxMjN9...'
                  refresh:
                    type: string
                    description: リフレッシュトークン
                    example: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0MzUwMDgwMCwiaWF0IjoxNjQwOTA4ODAwLCJqdGkiOiIwOTg3NjU0MzIxIiwidXNlcl9pZCI6MTIzfQ...'
              examples:
                success:
                  summary: トークン取得成功
                  value:
                    access: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImp0aSI6IjEyMzQ1Njc4OTAiLCJ1c2VyX2lkIjoxMjN9...'
                    refresh: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0MzUwMDgwMCwiaWF0IjoxNjQwOTA4ODAwLCJqdGkiOiIwOTg3NjU0MzIxIiwidXNlcl9pZCI6MTIzfQ...'
        '400':
          description: リクエストエラー
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: エラーメッセージ
              examples:
                validation_error:
                  summary: バリデーションエラー
                  value:
                    username: ['この項目は必須です。']
                    password: ['この項目は必須です。']
        '401':
          description: 認証エラー
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: エラーメッセージ
              examples:
                no_active_account:
                  summary: アカウントが無効
                  value:
                    detail: 'No active account found with the given credentials'
                invalid_end_user:
                  summary: 無効なエンドユーザー
                  value:
                    detail: 'Invalid end user ID'
                invalid_end_user_password:
                  summary: 無効なエンドユーザーパスワード
                  value:
                    detail: 'Invalid end user password'
        '500':
          description: サーバーエラー
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: '内部サーバーエラー'

  /api/v2/token/refresh:
    post:
      summary: アクセストークン更新
      description: リフレッシュトークンを使用して新しいアクセストークンを取得します
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - refresh
              properties:
                refresh:
                  type: string
                  description: リフレッシュトークン
                  example: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0MzUwMDgwMCwiaWF0IjoxNjQwOTA4ODAwLCJqdGkiOiIwOTg3NjU0MzIxIiwidXNlcl9pZCI6MTIzfQ...'
      responses:
        '200':
          description: アクセストークン更新成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  access:
                    type: string
                    description: 新しいアクセストークン
                    example: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImp0aSI6IjEyMzQ1Njc4OTAiLCJ1c2VyX2lkIjoxMjN9...'
        '401':
          description: 無効なリフレッシュトークン
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: エラーメッセージ
                    example: 'Token is invalid or expired'

  /api/v2/token/verify:
    post:
      summary: トークン検証
      description: トークンの有効性を検証します
      tags:
        - Authentication
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - token
              properties:
                token:
                  type: string
                  description: 検証するトークン（アクセストークンまたはリフレッシュトークン）
                  example: 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQwOTk1MjAwLCJpYXQiOjE2NDA5MDg4MDAsImp0aSI6IjEyMzQ1Njc4OTAiLCJ1c2VyX2lkIjoxMjN9...'
      responses:
        '200':
          description: 送信されたトークンが有効の場合は200を返します
          content:
            application/json:
              schema:
                type: object
                properties: {}
        '401':
          description: 無効なトークン
          content:
            application/json:
              schema:
                type: object
                properties:
                  detail:
                    type: string
                    description: エラーメッセージ
                    example: 'Token is invalid or expired'

components:
  schemas:
    TokenResponse:
      type: object
      properties:
        access:
          type: string
          description: アクセストークン（有効期限1日）
        refresh:
          type: string
          description: リフレッシュトークン（有効期限30日）

tags:
  - name: Authentication
    description: 認証関連API
