openapi: 3.1.0
info:
  title: Sonogo API
  version: '1.0'
  description: |-
    Sonogo (sono-5.com) の全機能を JSON でアクセスできる REST API。
    顧客・資料・閲覧セッション・メール・通知・チーム・Webhook を一通り読み書きできる。
    外部サイトからのリード登録から、社内 BI / SOR への同期、自動化バックエンド (Zapier, n8n, AI エージェント) まで同じ API キーで叩ける。

    - 形式: JSON (request / response)
    - 認証: API キー (Bearer token)
    - CORS: `Access-Control-Allow-Origin: *`
    - HTTPS 必須
  contact:
    name: Sonogo Support
    url: https://sono-5.com/contact
servers:
  - url: https://sono-5.com
    description: Production
security:
  - ApiKeyAuth: []
tags:
  - name: Lead Submissions
    description: リード (顧客 + 送信イベント) 登録。外部 LP / 問合せフォーム → Sonogo の最短経路。
  - name: Customers
    description: 顧客の CRUD と顧客タイムライン (送信履歴・閲覧・メール) 取得。
  - name: Customer Tags
    description: 顧客タグの定義 CRUD。タグの付与は `/customers/{id}/tags` で行う。
  - name: Documents
    description: 資料 (PDF) のメタ CRUD とファイル差し替え履歴 (versions)。
  - name: Document Tags
    description: 資料タグの定義 CRUD。タグの付与は `/documents/{id}/tags` で行う。
  - name: Sessions
    description: viewer での資料閲覧セッションとページ別滞在時間。
  - name: Email Accounts
    description: 個別メール (IMAP/SMTP) アカウントの読み取り (パスワード等は含まない)。
  - name: Email Threads
    description: 個別メールのスレッド一覧 / 詳細 (メッセージ含む)。
  - name: Email Messages
    description: 個別メールのメッセージ単位の取得 / 既読化。
  - name: Notifications
    description: ログインユーザー宛の通知 (アプリ内通知)。
  - name: Team
    description: 現在のチーム情報・メンバー・招待。
  - name: Webhooks
    description: Sonogo → 外部 URL の Webhook 通知設定の CRUD と動作確認。
  - name: Outbound Webhooks
    description: Sonogo から外部 URL へ送信される通知 (受信側仕様)
components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: sk_live_*
      description: |-
        Sonogo の `/settings/api` で発行した API キーを Bearer token として送ります。
        例: `Authorization: Bearer sk_live_abcdef1234567890...`
        サーバサイド専用。ブラウザ JS に公開しないでください。
  schemas:
    Customer:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
          description: 顧客名 (必須、最大 200 文字)
          example: 山田太郎
        email:
          type: string
          maxLength: 254
          format: email
          description: メールアドレス (重複検出キー)
          example: yamada@example.com
        phone:
          type: string
          maxLength: 50
          description: 電話番号
        company_name:
          type: string
          maxLength: 200
          description: 会社名
          example: 株式会社サンプル
        fields:
          type: object
          additionalProperties: {}
          description: 拡張フィールド (任意 key/value)。`department` `position` `address` `notes` 等の既知 key は自動で日本語ラベル化される。顧客プロフィールに恒久保存され、Slack/メール通知の本文にも含まれる。
      required:
        - name
    Payload:
      type: object
      properties:
        subject:
          type: string
          maxLength: 500
          description: 件名 (問合せ等、最大 500 文字)
        message:
          type: string
          maxLength: 10000
          description: 本文 (問合せ等、最大 10,000 文字)
        document_id:
          type: string
          format: uuid
          description: 資料 ID (指定時はトラッキングリンクも自動発行)
      additionalProperties: {}
      description: 'チャネル固有データを passthrough。代表フィールドは subject / message / document_id。任意 key を追加可能 (例: `preferred_schedule`)。送信単位で `lead_submissions.payload` に保存され、Slack/メール通知の本文にも含まれる。タイムラインに出るのは `subject` / `message` のみ。'
    Context:
      type: object
      properties:
        utm_source:
          type: string
          maxLength: 200
        utm_medium:
          type: string
          maxLength: 200
        utm_campaign:
          type: string
          maxLength: 200
        utm_term:
          type: string
          maxLength: 200
        utm_content:
          type: string
          maxLength: 200
        referrer:
          type: string
          maxLength: 2000
        landing_url:
          type: string
          maxLength: 2000
      description: 流入計測用メタ情報
    LeadSubmissionRequest:
      type: object
      properties:
        source:
          type: string
          enum:
            - document_download
            - inquiry
            - webinar
            - newsletter
            - trial
            - custom
            - manual
          description: 流入種別 (必須)
        customer:
          $ref: '#/components/schemas/Customer'
        payload:
          $ref: '#/components/schemas/Payload'
        context:
          $ref: '#/components/schemas/Context'
        tags:
          type: array
          items:
            type: string
            maxLength: 100
          maxItems: 20
          description: タグ名 (最大 20 個)。未存在は自動作成。複数フォームを区別したいときはタグで分ける
      required:
        - source
        - customer
      description: リード（資料DL・問い合わせ等）を登録する。`source` で種別を指定し、複数フォームを区別したい場合は `tags` で分ける。
    LeadSubmissionResponse:
      type: object
      properties:
        customer:
          type: object
          properties:
            id:
              type: string
              format: uuid
            name:
              type: string
            email:
              type:
                - string
                - 'null'
            company_name:
              type:
                - string
                - 'null'
            reused:
              type: boolean
              description: true なら既存顧客 (email 一致) を再利用
          required:
            - id
            - name
            - email
            - company_name
            - reused
        submission:
          type: object
          properties:
            id:
              type: string
              format: uuid
            source:
              type: string
              enum:
                - document_download
                - inquiry
                - webinar
                - newsletter
                - trial
                - custom
                - manual
            created_at:
              type: string
              format: date-time
          required:
            - id
            - source
            - created_at
        tracking_link:
          type:
            - object
            - 'null'
          properties:
            id:
              type: string
              format: uuid
            url:
              type: string
              format: uri
            document_id:
              type: string
              format: uuid
            unique_id:
              type: string
          required:
            - id
            - url
            - document_id
            - unique_id
          description: payload.document_id 指定時のみ。それ以外は null。
      required:
        - customer
        - submission
        - tracking_link
    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: ヒューマンリーダブルなエラーメッセージ
        details:
          type: object
          additionalProperties: {}
          description: バリデーションエラー時のフィールド別詳細
      required:
        - error
    WebhookEvent:
      type: object
      properties:
        event:
          type: string
          enum:
            - lead_created
            - viewing
            - completed
            - email_opened
            - email_clicked
            - email_replied
            - imap_opened
            - imap_clicked
            - imap_watched_sender
            - imap_scheduled_sent
            - imap_scheduled_failed
        occurred_at:
          type: string
          format: date-time
        team_id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        data:
          type: object
          properties:
            title:
              type: string
            body:
              type: string
            action_url:
              type:
                - string
                - 'null'
              format: uri
            customer:
              type:
                - object
                - 'null'
              properties:
                id:
                  type:
                    - string
                    - 'null'
                  format: uuid
                name:
                  type:
                    - string
                    - 'null'
                email:
                  type:
                    - string
                    - 'null'
                phone:
                  type:
                    - string
                    - 'null'
                company_name:
                  type:
                    - string
                    - 'null'
            assignee:
              type:
                - string
                - 'null'
            document_id:
              type:
                - string
                - 'null'
              format: uuid
            email_id:
              type:
                - string
                - 'null'
              format: uuid
            email_message_id:
              type:
                - string
                - 'null'
          required:
            - title
            - body
            - action_url
            - customer
            - assignee
            - document_id
            - email_id
            - email_message_id
      required:
        - event
        - occurred_at
        - team_id
        - organization_id
        - data
      description: Sonogo から外部 URL に POST されるイベント (outbound webhook)。/settings/notifications の「Webhook 連携」で登録した URL に配信されます。Discord/Teams/Google Chat の URL は自動でリッチメッセージに整形されます (このスキーマは汎用 JSON 配信時のもの)。
    CustomerObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        email:
          type:
            - string
            - 'null'
        phone:
          type:
            - string
            - 'null'
        company_name:
          type:
            - string
            - 'null'
        notes:
          type:
            - string
            - 'null'
        fields:
          type:
            - object
            - 'null'
          additionalProperties: {}
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        tags:
          type: array
          items:
            $ref: '#/components/schemas/CustomerTagRef'
        assignees:
          type: array
          items:
            $ref: '#/components/schemas/CustomerAssignee'
        stats:
          type: object
          properties:
            link_count:
              type: integer
            document_count:
              type: integer
            total_views:
              type: integer
            last_viewed_at:
              type:
                - string
                - 'null'
              format: date-time
            email_open_count:
              type: integer
          required:
            - link_count
            - document_count
            - total_views
            - last_viewed_at
            - email_open_count
      required:
        - id
        - name
        - email
        - phone
        - company_name
        - notes
        - fields
        - created_at
        - updated_at
        - tags
        - assignees
        - stats
    CustomerTagRef:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        color:
          type: string
      required:
        - id
        - name
        - color
    CustomerAssignee:
      type: object
      properties:
        id:
          type: string
          format: uuid
        full_name:
          type:
            - string
            - 'null'
        email:
          type: string
        avatar_url:
          type:
            - string
            - 'null'
      required:
        - id
        - full_name
        - email
        - avatar_url
    CustomerListResponse:
      type: object
      properties:
        customers:
          type: array
          items:
            $ref: '#/components/schemas/Customer'
        next_cursor:
          type:
            - string
            - 'null'
          description: 次ページ取得用 cursor。null なら最後
      required:
        - customers
        - next_cursor
    CustomerListQuery:
      type: object
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        cursor:
          type: string
          description: 前回レスポンスの next_cursor を渡す
        search:
          type: string
          description: name / email / company_name 部分一致
        tag_id:
          type: string
          format: uuid
          description: タグでフィルタ
    CustomerCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        email:
          type:
            - string
            - 'null'
          maxLength: 254
          format: email
        phone:
          type:
            - string
            - 'null'
          maxLength: 50
        company_name:
          type:
            - string
            - 'null'
          maxLength: 200
        notes:
          type:
            - string
            - 'null'
          maxLength: 10000
        fields:
          type:
            - object
            - 'null'
          additionalProperties: {}
        tag_ids:
          type: array
          items:
            type: string
            format: uuid
          maxItems: 50
      required:
        - name
    CustomerUpdateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        email:
          type:
            - string
            - 'null'
          maxLength: 254
          format: email
        phone:
          type:
            - string
            - 'null'
          maxLength: 50
        company_name:
          type:
            - string
            - 'null'
          maxLength: 200
        notes:
          type:
            - string
            - 'null'
          maxLength: 10000
        fields:
          type:
            - object
            - 'null'
          additionalProperties: {}
    CustomerTagSetRequest:
      type: object
      properties:
        tag_ids:
          type: array
          items:
            type: string
            format: uuid
          maxItems: 50
      required:
        - tag_ids
    CustomerTagListResponse:
      type: object
      properties:
        tags:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/CustomerTagRef'
              - type: object
                properties:
                  sort_order:
                    type: integer
                  customer_count:
                    type: integer
                required:
                  - sort_order
      required:
        - tags
    CustomerTagCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        color:
          type: string
          pattern: ^#[0-9a-fA-F]{6}$
        sort_order:
          type: integer
      required:
        - name
        - color
    CustomerTagUpdateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        color:
          type: string
          pattern: ^#[0-9a-fA-F]{6}$
        sort_order:
          type: integer
    CustomerTimelineResponse:
      type: object
      properties:
        events:
          type: array
          items:
            $ref: '#/components/schemas/CustomerTimelineEvent'
      required:
        - events
    CustomerTimelineEvent:
      type: object
      properties:
        type:
          type: string
          enum:
            - lead_submission
            - viewing_session
            - email_thread
            - tracking_link_created
        occurred_at:
          type: string
          format: date-time
        id:
          type: string
        title:
          type: string
        summary:
          type:
            - string
            - 'null'
        metadata:
          type:
            - object
            - 'null'
          additionalProperties: {}
      required:
        - type
        - occurred_at
        - id
        - title
        - summary
        - metadata
    DocumentObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        title:
          type: string
        description:
          type:
            - string
            - 'null'
        original_file_url:
          type:
            - string
            - 'null'
        original_file_name:
          type:
            - string
            - 'null'
        thumbnail_url:
          type:
            - string
            - 'null'
        page_count:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        tags:
          type: array
          items:
            $ref: '#/components/schemas/DocumentTagRef'
      required:
        - id
        - title
        - description
        - original_file_url
        - original_file_name
        - thumbnail_url
        - page_count
        - created_at
        - updated_at
        - tags
    DocumentTagRef:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        color:
          type: string
      required:
        - id
        - name
        - color
    DocumentDetail:
      allOf:
        - $ref: '#/components/schemas/Document'
        - type: object
          properties:
            versions:
              type: array
              items:
                $ref: '#/components/schemas/DocumentFileVersion'
          required:
            - versions
    DocumentFileVersion:
      type: object
      properties:
        id:
          type: string
          format: uuid
        document_id:
          type: string
          format: uuid
        version_number:
          type: integer
        original_file_url:
          type: string
        original_file_name:
          type:
            - string
            - 'null'
        thumbnail_url:
          type:
            - string
            - 'null'
        page_count:
          type: integer
        created_at:
          type: string
          format: date-time
      required:
        - id
        - document_id
        - version_number
        - original_file_url
        - original_file_name
        - thumbnail_url
        - page_count
        - created_at
    Document:
      type: object
      properties:
        id:
          type: string
          format: uuid
        title:
          type: string
        description:
          type:
            - string
            - 'null'
        original_file_url:
          type:
            - string
            - 'null'
        original_file_name:
          type:
            - string
            - 'null'
        thumbnail_url:
          type:
            - string
            - 'null'
        page_count:
          type: integer
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        tags:
          type: array
          items:
            $ref: '#/components/schemas/DocumentTagRef'
      required:
        - id
        - title
        - description
        - original_file_url
        - original_file_name
        - thumbnail_url
        - page_count
        - created_at
        - updated_at
        - tags
    DocumentListResponse:
      type: object
      properties:
        documents:
          type: array
          items:
            $ref: '#/components/schemas/Document'
        next_cursor:
          type:
            - string
            - 'null'
      required:
        - documents
        - next_cursor
    DocumentListQuery:
      type: object
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        cursor:
          type: string
        search:
          type: string
        tag_id:
          type: string
          format: uuid
    DocumentCreateRequest:
      type: object
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 200
        description:
          type:
            - string
            - 'null'
          maxLength: 10000
        original_file_url:
          type:
            - string
            - 'null'
          format: uri
        original_file_name:
          type:
            - string
            - 'null'
          maxLength: 500
        thumbnail_url:
          type:
            - string
            - 'null'
          format: uri
        page_count:
          type: integer
          minimum: 0
        tag_ids:
          type: array
          items:
            type: string
            format: uuid
          maxItems: 50
      required:
        - title
    DocumentUpdateRequest:
      type: object
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 200
        description:
          type:
            - string
            - 'null'
          maxLength: 10000
        original_file_url:
          type:
            - string
            - 'null'
          format: uri
        original_file_name:
          type:
            - string
            - 'null'
          maxLength: 500
        thumbnail_url:
          type:
            - string
            - 'null'
          format: uri
        page_count:
          type: integer
          minimum: 0
    DocumentTagSetRequest:
      type: object
      properties:
        tag_ids:
          type: array
          items:
            type: string
            format: uuid
          maxItems: 50
      required:
        - tag_ids
    DocumentTagListResponse:
      type: object
      properties:
        tags:
          type: array
          items:
            allOf:
              - $ref: '#/components/schemas/DocumentTagRef'
              - type: object
                properties:
                  sort_order:
                    type: integer
                required:
                  - sort_order
      required:
        - tags
    DocumentTagCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        color:
          type: string
          pattern: ^#[0-9a-fA-F]{6}$
        sort_order:
          type: integer
      required:
        - name
        - color
    DocumentTagUpdateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        color:
          type: string
          pattern: ^#[0-9a-fA-F]{6}$
        sort_order:
          type: integer
    SessionObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tracking_link_id:
          type: string
          format: uuid
        document_id:
          type: string
          format: uuid
        file_version_id:
          type:
            - string
            - 'null'
          format: uuid
        customer_id:
          type:
            - string
            - 'null'
          format: uuid
        started_at:
          type: string
          format: date-time
        ended_at:
          type:
            - string
            - 'null'
          format: date-time
        duration_seconds:
          type:
            - integer
            - 'null'
        inactive_seconds:
          type: integer
        is_active:
          type: boolean
        is_member_access:
          type: boolean
        pages_viewed:
          type: integer
        total_pages:
          type: integer
        completion_rate:
          type: number
        end_reason:
          type:
            - string
            - 'null'
        ip_address:
          type:
            - string
            - 'null'
        user_agent:
          type:
            - string
            - 'null'
        device_type:
          type:
            - string
            - 'null'
        browser_name:
          type:
            - string
            - 'null'
        os_name:
          type:
            - string
            - 'null'
        geo_country:
          type:
            - string
            - 'null'
        geo_region:
          type:
            - string
            - 'null'
        geo_city:
          type:
            - string
            - 'null'
        access_quality:
          type: string
        referrer:
          type:
            - string
            - 'null'
      required:
        - id
        - tracking_link_id
        - document_id
        - file_version_id
        - customer_id
        - started_at
        - ended_at
        - duration_seconds
        - inactive_seconds
        - is_active
        - is_member_access
        - pages_viewed
        - total_pages
        - completion_rate
        - end_reason
        - ip_address
        - user_agent
        - device_type
        - browser_name
        - os_name
        - geo_country
        - geo_region
        - geo_city
        - access_quality
        - referrer
    SessionDetail:
      allOf:
        - $ref: '#/components/schemas/Session'
        - type: object
          properties:
            page_dwell_times:
              type: array
              items:
                $ref: '#/components/schemas/PageDwell'
          required:
            - page_dwell_times
    PageDwell:
      type: object
      properties:
        page_number:
          type: integer
        dwell_time_ms:
          type: integer
        enter_count:
          type: integer
        file_version_id:
          type:
            - string
            - 'null'
          format: uuid
      required:
        - page_number
        - dwell_time_ms
        - enter_count
        - file_version_id
    Session:
      type: object
      properties:
        id:
          type: string
          format: uuid
        tracking_link_id:
          type: string
          format: uuid
        document_id:
          type: string
          format: uuid
        file_version_id:
          type:
            - string
            - 'null'
          format: uuid
        customer_id:
          type:
            - string
            - 'null'
          format: uuid
        started_at:
          type: string
          format: date-time
        ended_at:
          type:
            - string
            - 'null'
          format: date-time
        duration_seconds:
          type:
            - integer
            - 'null'
        inactive_seconds:
          type: integer
        is_active:
          type: boolean
        is_member_access:
          type: boolean
        pages_viewed:
          type: integer
        total_pages:
          type: integer
        completion_rate:
          type: number
        end_reason:
          type:
            - string
            - 'null'
        ip_address:
          type:
            - string
            - 'null'
        user_agent:
          type:
            - string
            - 'null'
        device_type:
          type:
            - string
            - 'null'
        browser_name:
          type:
            - string
            - 'null'
        os_name:
          type:
            - string
            - 'null'
        geo_country:
          type:
            - string
            - 'null'
        geo_region:
          type:
            - string
            - 'null'
        geo_city:
          type:
            - string
            - 'null'
        access_quality:
          type: string
        referrer:
          type:
            - string
            - 'null'
      required:
        - id
        - tracking_link_id
        - document_id
        - file_version_id
        - customer_id
        - started_at
        - ended_at
        - duration_seconds
        - inactive_seconds
        - is_active
        - is_member_access
        - pages_viewed
        - total_pages
        - completion_rate
        - end_reason
        - ip_address
        - user_agent
        - device_type
        - browser_name
        - os_name
        - geo_country
        - geo_region
        - geo_city
        - access_quality
        - referrer
    SessionListResponse:
      type: object
      properties:
        sessions:
          type: array
          items:
            $ref: '#/components/schemas/Session'
        next_cursor:
          type:
            - string
            - 'null'
      required:
        - sessions
        - next_cursor
    SessionListQuery:
      type: object
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        cursor:
          type: string
        customer_id:
          type: string
          format: uuid
        document_id:
          type: string
          format: uuid
        since:
          type: string
          format: date-time
        until:
          type: string
          format: date-time
        include_member_views:
          type:
            - boolean
            - 'null'
          default: false
    EmailAccountListResponse:
      type: object
      properties:
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/EmailAccount'
      required:
        - accounts
    EmailAccount:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        label:
          type: string
        email_address:
          type: string
        imap_host:
          type: string
        imap_port:
          type: integer
        imap_user:
          type: string
        imap_secure:
          type: boolean
        smtp_host:
          type: string
        smtp_port:
          type: integer
        smtp_user:
          type: string
        smtp_secure:
          type: boolean
        sync_folders:
          type: array
          items:
            type: string
        visibility:
          type: string
        is_active:
          type: boolean
        last_sync_at:
          type:
            - string
            - 'null'
          format: date-time
        last_sync_error:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - user_id
        - team_id
        - organization_id
        - label
        - email_address
        - imap_host
        - imap_port
        - imap_user
        - imap_secure
        - smtp_host
        - smtp_port
        - smtp_user
        - smtp_secure
        - sync_folders
        - visibility
        - is_active
        - last_sync_at
        - last_sync_error
        - created_at
        - updated_at
    EmailThreadListResponse:
      type: object
      properties:
        threads:
          type: array
          items:
            $ref: '#/components/schemas/EmailThread'
        next_cursor:
          type:
            - string
            - 'null'
      required:
        - threads
        - next_cursor
    EmailThread:
      type: object
      properties:
        id:
          type: string
          format: uuid
        account_id:
          type:
            - string
            - 'null'
          format: uuid
        customer_id:
          type:
            - string
            - 'null'
          format: uuid
        subject:
          type: string
        snippet:
          type: string
        message_count:
          type: integer
        is_read:
          type: boolean
        is_starred:
          type: boolean
        has_sonogo_message:
          type:
            - boolean
            - 'null'
        last_message_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - account_id
        - customer_id
        - subject
        - snippet
        - message_count
        - is_read
        - is_starred
        - has_sonogo_message
        - last_message_at
        - created_at
        - updated_at
    EmailThreadListQuery:
      type: object
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        cursor:
          type: string
        account_id:
          type: string
          format: uuid
        customer_id:
          type: string
          format: uuid
        is_read:
          type:
            - boolean
            - 'null'
    EmailThreadDetail:
      allOf:
        - $ref: '#/components/schemas/EmailThread'
        - type: object
          properties:
            messages:
              type: array
              items:
                $ref: '#/components/schemas/EmailMessage'
          required:
            - messages
    EmailMessage:
      type: object
      properties:
        id:
          type: string
          format: uuid
        thread_id:
          type: string
          format: uuid
        account_id:
          type:
            - string
            - 'null'
          format: uuid
        direction:
          type: string
          enum:
            - inbound
            - outbound
            - draft
        folder:
          type: string
        from_address:
          type: string
        from_name:
          type: string
        to_addresses: {}
        cc_addresses: {}
        bcc_addresses: {}
        subject:
          type: string
        body_text:
          type:
            - string
            - 'null'
        body_html:
          type:
            - string
            - 'null'
        is_read:
          type: boolean
        in_reply_to:
          type:
            - string
            - 'null'
        references_header:
          type:
            - string
            - 'null'
        message_id_header:
          type:
            - string
            - 'null'
        has_tracking_pixel:
          type: boolean
        send_status:
          type: string
        send_error:
          type:
            - string
            - 'null'
        scheduled_at:
          type:
            - string
            - 'null'
          format: date-time
        sent_at:
          type:
            - string
            - 'null'
          format: date-time
        received_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - thread_id
        - account_id
        - direction
        - folder
        - from_address
        - from_name
        - subject
        - body_text
        - body_html
        - is_read
        - in_reply_to
        - references_header
        - message_id_header
        - has_tracking_pixel
        - send_status
        - send_error
        - scheduled_at
        - sent_at
        - received_at
        - created_at
        - updated_at
    EmailMessageObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        thread_id:
          type: string
          format: uuid
        account_id:
          type:
            - string
            - 'null'
          format: uuid
        direction:
          type: string
          enum:
            - inbound
            - outbound
            - draft
        folder:
          type: string
        from_address:
          type: string
        from_name:
          type: string
        to_addresses: {}
        cc_addresses: {}
        bcc_addresses: {}
        subject:
          type: string
        body_text:
          type:
            - string
            - 'null'
        body_html:
          type:
            - string
            - 'null'
        is_read:
          type: boolean
        in_reply_to:
          type:
            - string
            - 'null'
        references_header:
          type:
            - string
            - 'null'
        message_id_header:
          type:
            - string
            - 'null'
        has_tracking_pixel:
          type: boolean
        send_status:
          type: string
        send_error:
          type:
            - string
            - 'null'
        scheduled_at:
          type:
            - string
            - 'null'
          format: date-time
        sent_at:
          type:
            - string
            - 'null'
          format: date-time
        received_at:
          type: string
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - thread_id
        - account_id
        - direction
        - folder
        - from_address
        - from_name
        - subject
        - body_text
        - body_html
        - is_read
        - in_reply_to
        - references_header
        - message_id_header
        - has_tracking_pixel
        - send_status
        - send_error
        - scheduled_at
        - sent_at
        - received_at
        - created_at
        - updated_at
    EmailMessageUpdateRequest:
      type: object
      properties:
        is_read:
          type: boolean
    NotificationObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - opened
            - viewing
            - completed
            - email_opened
            - email_clicked
            - email_delivered
            - email_bounced
            - email_unsubscribed
            - email_complained
            - email_replied
            - imap_opened
            - imap_clicked
            - lead_created
            - imap_watched_sender
            - imap_scheduled_sent
            - imap_scheduled_failed
        title:
          type: string
        body:
          type:
            - string
            - 'null'
        is_read:
          type: boolean
        customer_id:
          type:
            - string
            - 'null'
          format: uuid
        document_id:
          type:
            - string
            - 'null'
          format: uuid
        email_id:
          type:
            - string
            - 'null'
          format: uuid
        email_message_id:
          type:
            - string
            - 'null'
          format: uuid
        session_id:
          type:
            - string
            - 'null'
          format: uuid
        tracking_link_id:
          type:
            - string
            - 'null'
          format: uuid
        created_at:
          type: string
          format: date-time
      required:
        - id
        - type
        - title
        - body
        - is_read
        - customer_id
        - document_id
        - email_id
        - email_message_id
        - session_id
        - tracking_link_id
        - created_at
    NotificationListResponse:
      type: object
      properties:
        notifications:
          type: array
          items:
            $ref: '#/components/schemas/Notification'
        next_cursor:
          type:
            - string
            - 'null'
      required:
        - notifications
        - next_cursor
    Notification:
      type: object
      properties:
        id:
          type: string
          format: uuid
        type:
          type: string
          enum:
            - opened
            - viewing
            - completed
            - email_opened
            - email_clicked
            - email_delivered
            - email_bounced
            - email_unsubscribed
            - email_complained
            - email_replied
            - imap_opened
            - imap_clicked
            - lead_created
            - imap_watched_sender
            - imap_scheduled_sent
            - imap_scheduled_failed
        title:
          type: string
        body:
          type:
            - string
            - 'null'
        is_read:
          type: boolean
        customer_id:
          type:
            - string
            - 'null'
          format: uuid
        document_id:
          type:
            - string
            - 'null'
          format: uuid
        email_id:
          type:
            - string
            - 'null'
          format: uuid
        email_message_id:
          type:
            - string
            - 'null'
          format: uuid
        session_id:
          type:
            - string
            - 'null'
          format: uuid
        tracking_link_id:
          type:
            - string
            - 'null'
          format: uuid
        created_at:
          type: string
          format: date-time
      required:
        - id
        - type
        - title
        - body
        - is_read
        - customer_id
        - document_id
        - email_id
        - email_message_id
        - session_id
        - tracking_link_id
        - created_at
    NotificationListQuery:
      type: object
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 200
          default: 50
        cursor:
          type: string
        is_read:
          type:
            - boolean
            - 'null'
        type:
          type: string
          enum:
            - opened
            - viewing
            - completed
            - email_opened
            - email_clicked
            - email_delivered
            - email_bounced
            - email_unsubscribed
            - email_complained
            - email_replied
            - imap_opened
            - imap_clicked
            - lead_created
            - imap_watched_sender
            - imap_scheduled_sent
            - imap_scheduled_failed
    NotificationUpdateRequest:
      type: object
      properties:
        is_read:
          type: boolean
      required:
        - is_read
    NotificationUnreadCount:
      type: object
      properties:
        count:
          type: integer
      required:
        - count
    TeamObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        name:
          type: string
        icon_url:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - organization_id
        - name
        - icon_url
        - created_at
        - updated_at
    TeamMemberListResponse:
      type: object
      properties:
        members:
          type: array
          items:
            $ref: '#/components/schemas/TeamMember'
      required:
        - members
    TeamMember:
      type: object
      properties:
        id:
          type: string
          format: uuid
        user_id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        joined_at:
          type: string
          format: date-time
        role:
          type: string
        permissions:
          type: array
          items:
            type: string
            enum:
              - org_admin
              - billing_admin
        profile:
          type: object
          properties:
            id:
              type: string
              format: uuid
            email:
              type: string
            full_name:
              type:
                - string
                - 'null'
            avatar_url:
              type:
                - string
                - 'null'
          required:
            - id
            - email
            - full_name
            - avatar_url
      required:
        - id
        - user_id
        - team_id
        - joined_at
        - role
        - permissions
        - profile
    TeamInviteObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        email:
          type: string
        role:
          type: string
        grant_permissions:
          type: array
          items:
            type: string
            enum:
              - org_admin
              - billing_admin
        invited_by:
          type: string
          format: uuid
        token:
          type: string
        expires_at:
          type: string
          format: date-time
        accepted_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
      required:
        - id
        - team_id
        - email
        - role
        - grant_permissions
        - invited_by
        - token
        - expires_at
        - accepted_at
        - created_at
    TeamInviteListResponse:
      type: object
      properties:
        invites:
          type: array
          items:
            $ref: '#/components/schemas/TeamInvite'
      required:
        - invites
    TeamInvite:
      type: object
      properties:
        id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        email:
          type: string
        role:
          type: string
        grant_permissions:
          type: array
          items:
            type: string
            enum:
              - org_admin
              - billing_admin
        invited_by:
          type: string
          format: uuid
        token:
          type: string
        expires_at:
          type: string
          format: date-time
        accepted_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
      required:
        - id
        - team_id
        - email
        - role
        - grant_permissions
        - invited_by
        - token
        - expires_at
        - accepted_at
        - created_at
    TeamInviteCreateRequest:
      type: object
      properties:
        email:
          type: string
          format: email
        grant_permissions:
          type: array
          items:
            type: string
            enum:
              - org_admin
              - billing_admin
          maxItems: 2
      required:
        - email
    WebhookObject:
      type: object
      properties:
        id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        name:
          type: string
        url:
          type: string
        event_types:
          type: array
          items:
            type: string
        is_active:
          type: boolean
        last_status:
          type:
            - integer
            - 'null'
        last_error:
          type:
            - string
            - 'null'
        last_fired_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - team_id
        - organization_id
        - name
        - url
        - event_types
        - is_active
        - last_status
        - last_error
        - last_fired_at
        - created_at
        - updated_at
    WebhookListResponse:
      type: object
      properties:
        webhooks:
          type: array
          items:
            $ref: '#/components/schemas/Webhook'
      required:
        - webhooks
    Webhook:
      type: object
      properties:
        id:
          type: string
          format: uuid
        team_id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        name:
          type: string
        url:
          type: string
        event_types:
          type: array
          items:
            type: string
        is_active:
          type: boolean
        last_status:
          type:
            - integer
            - 'null'
        last_error:
          type:
            - string
            - 'null'
        last_fired_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - team_id
        - organization_id
        - name
        - url
        - event_types
        - is_active
        - last_status
        - last_error
        - last_fired_at
        - created_at
        - updated_at
    WebhookCreateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        url:
          type: string
          format: uri
        event_types:
          type: array
          items:
            type: string
            enum:
              - lead_created
              - viewing
              - completed
              - email_opened
              - email_clicked
              - email_replied
              - imap_opened
              - imap_clicked
              - imap_watched_sender
              - imap_scheduled_sent
              - imap_scheduled_failed
          minItems: 1
        secret:
          type:
            - string
            - 'null'
          maxLength: 500
        is_active:
          type: boolean
      required:
        - name
        - url
        - event_types
    WebhookUpdateRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 200
        url:
          type: string
          format: uri
        event_types:
          type: array
          items:
            type: string
            enum:
              - lead_created
              - viewing
              - completed
              - email_opened
              - email_clicked
              - email_replied
              - imap_opened
              - imap_clicked
              - imap_watched_sender
              - imap_scheduled_sent
              - imap_scheduled_failed
          minItems: 1
        secret:
          type:
            - string
            - 'null'
          maxLength: 500
        is_active:
          type: boolean
    WebhookTestResponse:
      type: object
      properties:
        ok:
          type: boolean
        status:
          type: integer
        error:
          type:
            - string
            - 'null'
        kind:
          type: string
      required:
        - ok
        - status
        - error
        - kind
    DeletedResponse:
      type: object
      properties:
        deleted:
          type: boolean
        id:
          type: string
        token:
          type: string
      required:
        - deleted
    TagObjectResponse:
      type: object
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        color:
          type: string
        sort_order:
          type: integer
      required:
        - id
        - name
        - color
    MarkAllReadResponse:
      type: object
      properties:
        updated:
          type: integer
      required:
        - updated
    Team:
      type: object
      properties:
        id:
          type: string
          format: uuid
        organization_id:
          type: string
          format: uuid
        name:
          type: string
        icon_url:
          type:
            - string
            - 'null'
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
      required:
        - id
        - organization_id
        - name
        - icon_url
        - created_at
        - updated_at
  parameters: {}
paths:
  /api/v1/lead-submissions:
    post:
      summary: リードを登録
      description: |-
        同一 team 内で email が一致する顧客があれば再利用、無ければ新規作成。
        送信のたびに `lead_submissions` に 1 行 append され、顧客タイムラインに表示されます。
        `payload.document_id` を指定するとトラッキングリンクも自動発行されます。
      operationId: createLeadSubmission
      tags:
        - Lead Submissions
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LeadSubmissionRequest'
            examples:
              inquiry:
                summary: 問合せフォーム
                value:
                  source: inquiry
                  customer:
                    name: 山田太郎
                    email: yamada@example.com
                    company_name: 株式会社サンプル
                  payload:
                    subject: 料金について
                    message: 詳しい料金を知りたいです
                  context:
                    utm_source: google
                    utm_campaign: spring-2026
                  tags:
                    - 問合せ
              document_download:
                summary: 資料ダウンロード
                value:
                  source: document_download
                  customer:
                    name: 山田太郎
                    email: yamada@example.com
                    company_name: 株式会社サンプル
                    fields:
                      department: 営業
                      position: 部長
                  payload:
                    document_id: 4f8c9b2a-1234-5678-9abc-def012345678
                  tags:
                    - 資料ダウンロード
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LeadSubmissionResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '410':
          description: フォームが無効化済み (アーカイブ等)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: &ref_0
            Retry-After:
              schema:
                type: integer
              description: 次回リクエスト可能までの秒数
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    options:
      summary: CORS preflight
      operationId: leadSubmissionsOptions
      tags:
        - Lead Submissions
      security: []
      responses:
        '204':
          description: CORS preflight 成功
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                example: '*'
            Access-Control-Allow-Methods:
              schema:
                type: string
                example: POST, OPTIONS
            Access-Control-Allow-Headers:
              schema:
                type: string
                example: Content-Type, Authorization
  /api/v1/customers:
    get:
      summary: 顧客一覧
      operationId: listCustomers
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
            description: 前回レスポンスの next_cursor を渡す
          required: false
          description: 前回レスポンスの next_cursor を渡す
          name: cursor
          in: query
        - schema:
            type: string
            description: name / email / company_name 部分一致
          required: false
          description: name / email / company_name 部分一致
          name: search
          in: query
        - schema:
            type: string
            format: uuid
            description: タグでフィルタ
          required: false
          description: タグでフィルタ
          name: tag_id
          in: query
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: 顧客を作成
      operationId: createCustomer
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: 同じ email の顧客が既存
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/customers/{id}:
    get:
      summary: 顧客を取得
      operationId: getCustomer
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      summary: 顧客を更新
      operationId: updateCustomer
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: 顧客を削除
      operationId: deleteCustomer
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/customers/{id}/tags:
    get:
      summary: 顧客のタグ一覧
      operationId: getCustomerTags
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  tags:
                    type: array
                    items:
                      $ref: '#/components/schemas/CustomerTagRef'
                required:
                  - tags
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      summary: 顧客のタグを置換
      operationId: setCustomerTags
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerTagSetRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  tags:
                    type: array
                    items:
                      $ref: '#/components/schemas/CustomerTagRef'
                required:
                  - tags
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/customers/{id}/timeline:
    get:
      summary: 顧客タイムライン
      operationId: getCustomerTimeline
      tags:
        - Customers
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerTimelineResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/customer-tags:
    get:
      summary: 顧客タグ一覧
      operationId: listCustomerTags
      tags:
        - Customer Tags
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomerTagListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: 顧客タグを作成
      operationId: createCustomerTag
      tags:
        - Customer Tags
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerTagCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagObjectResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: 同名タグが既存
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/customer-tags/{id}:
    patch:
      summary: 顧客タグを更新
      operationId: updateCustomerTag
      tags:
        - Customer Tags
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomerTagUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagObjectResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: 顧客タグを削除
      operationId: deleteCustomerTag
      tags:
        - Customer Tags
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/documents:
    get:
      summary: 資料一覧
      operationId: listDocuments
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: string
          required: false
          name: search
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: tag_id
          in: query
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: 資料を作成
      operationId: createDocument
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Document'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/documents/{id}:
    get:
      summary: 資料を取得
      operationId: getDocument
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentDetail'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      summary: 資料を更新
      operationId: updateDocument
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Document'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: 資料を削除
      operationId: deleteDocument
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/documents/{id}/versions:
    get:
      summary: 資料のバージョン一覧
      operationId: listDocumentVersions
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  versions:
                    type: array
                    items:
                      $ref: '#/components/schemas/DocumentFileVersion'
                required:
                  - versions
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/documents/{id}/tags:
    get:
      summary: 資料のタグ一覧
      operationId: getDocumentTags
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentTagListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    put:
      summary: 資料のタグを置換
      operationId: setDocumentTags
      tags:
        - Documents
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentTagSetRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentTagListResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/document-tags:
    get:
      summary: 資料タグ一覧
      operationId: listDocumentTags
      tags:
        - Document Tags
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DocumentTagListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: 資料タグを作成
      operationId: createDocumentTag
      tags:
        - Document Tags
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentTagCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagObjectResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: 同名タグが既存
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/document-tags/{id}:
    patch:
      summary: 資料タグを更新
      operationId: updateDocumentTag
      tags:
        - Document Tags
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentTagUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagObjectResponse'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: 資料タグを削除
      operationId: deleteDocumentTag
      tags:
        - Document Tags
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/sessions:
    get:
      summary: 資料閲覧セッション一覧
      operationId: listSessions
      tags:
        - Sessions
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: customer_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: document_id
          in: query
        - schema:
            type: string
            format: date-time
          required: false
          name: since
          in: query
        - schema:
            type: string
            format: date-time
          required: false
          name: until
          in: query
        - schema:
            type:
              - boolean
              - 'null'
            default: false
          required: false
          name: include_member_views
          in: query
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/sessions/{id}:
    get:
      summary: 閲覧セッションを取得
      operationId: getSession
      tags:
        - Sessions
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionDetail'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/email-accounts:
    get:
      summary: メールアカウント一覧
      operationId: listEmailAccounts
      tags:
        - Email Accounts
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailAccountListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/email-threads:
    get:
      summary: メールスレッド一覧
      operationId: listEmailThreads
      tags:
        - Email Threads
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: account_id
          in: query
        - schema:
            type: string
            format: uuid
          required: false
          name: customer_id
          in: query
        - schema:
            type:
              - boolean
              - 'null'
          required: false
          name: is_read
          in: query
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailThreadListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/email-threads/{id}:
    get:
      summary: メールスレッドを取得 (本文含む)
      operationId: getEmailThread
      tags:
        - Email Threads
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailThreadDetail'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/email-messages/{id}:
    get:
      summary: メールメッセージを取得
      operationId: getEmailMessage
      tags:
        - Email Messages
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EmailMessage'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      summary: メールメッセージを更新 (既読化)
      operationId: updateEmailMessage
      tags:
        - Email Messages
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EmailMessageUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                  is_read:
                    type: boolean
                required:
                  - id
                  - is_read
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/notifications:
    get:
      summary: 通知一覧
      operationId: listNotifications
      tags:
        - Notifications
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
          required: false
          name: limit
          in: query
        - schema:
            type: string
          required: false
          name: cursor
          in: query
        - schema:
            type:
              - boolean
              - 'null'
          required: false
          name: is_read
          in: query
        - schema:
            type: string
            enum:
              - opened
              - viewing
              - completed
              - email_opened
              - email_clicked
              - email_delivered
              - email_bounced
              - email_unsubscribed
              - email_complained
              - email_replied
              - imap_opened
              - imap_clicked
              - lead_created
              - imap_watched_sender
              - imap_scheduled_sent
              - imap_scheduled_failed
          required: false
          name: type
          in: query
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/notifications/unread-count:
    get:
      summary: 未読通知数を取得
      operationId: getNotificationUnreadCount
      tags:
        - Notifications
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NotificationUnreadCount'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/notifications/{id}:
    patch:
      summary: 通知を既読/未読化
      operationId: updateNotification
      tags:
        - Notifications
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NotificationUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                  is_read:
                    type: boolean
                required:
                  - id
                  - is_read
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/notifications/mark-all-read:
    post:
      summary: 通知を全件既読化
      operationId: markAllNotificationsRead
      tags:
        - Notifications
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MarkAllReadResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/team:
    get:
      summary: 現在のチーム情報
      operationId: getTeam
      tags:
        - Team
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Team'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/team/members:
    get:
      summary: チームメンバー一覧
      operationId: listTeamMembers
      tags:
        - Team
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamMemberListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/team/invites:
    get:
      summary: 招待中の一覧
      operationId: listTeamInvites
      tags:
        - Team
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamInviteListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: チーム招待を発行
      operationId: createTeamInvite
      tags:
        - Team
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TeamInviteCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TeamInvite'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: 同 email の有効な招待が既存
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/team/invites/{token}:
    delete:
      summary: 招待を取り消し
      operationId: revokeTeamInvite
      tags:
        - Team
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            description: 招待発行時の token
          required: true
          description: 招待発行時の token
          name: token
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/webhooks:
    get:
      summary: Webhook 一覧
      operationId: listWebhooks
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookListResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    post:
      summary: Webhook を登録
      operationId: createWebhook
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookCreateRequest'
      responses:
        '201':
          description: 作成成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/webhooks/{id}:
    get:
      summary: Webhook を取得
      operationId: getWebhook
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    patch:
      summary: Webhook を更新
      operationId: updateWebhook
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookUpdateRequest'
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Webhook'
        '400':
          description: リクエスト不正 (JSON パース失敗 / バリデーション)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
    delete:
      summary: Webhook を削除
      operationId: deleteWebhook
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DeletedResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
  /api/v1/webhooks/{id}/test:
    post:
      summary: Webhook 動作確認
      description: テストイベントを Webhook に送信します。誤発火防止のため 10 req/min に制限。
      operationId: testWebhook
      tags:
        - Webhooks
      security:
        - ApiKeyAuth: []
      parameters:
        - schema:
            type: string
            format: uuid
          required: true
          name: id
          in: path
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WebhookTestResponse'
        '400':
          description: リクエスト不正
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: API キー無効 / 失効
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: 権限不足 / クォータ超過
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: 対象リソース未発見
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: レート制限超過 (`Retry-After` ヘッダ参照)。GET は 120 req/min、書き込みは 60 req/min が既定。
          headers: *ref_0
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: サーバ内部エラー
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
webhooks:
  leadCreated:
    post:
      summary: lead_created (リード作成通知)
      tags:
        - Outbound Webhooks
      description: |-
        新しいリードが Sonogo に登録されたとき、登録された Webhook URL に POST します。
        他のイベント (viewing / completed / email_opened 等) も同じ形式で配信されます。

        ## 配信ポリシー
        - fire-and-forget、5 秒タイムアウト
        - 失敗時のリトライなし (運用観測のみ。`last_status` / `last_error` で確認可能)
        - 受信側で冪等性 (`occurred_at` + `customer_id` 等の組合せで重複検知) を担保推奨
        - 順序保証なし

        ## 署名検証
        Webhook 設定でシークレットを指定した場合、ペイロード本文の HMAC SHA256 が
        `X-Sonogo-Signature: sha256=<hex>` ヘッダに入ります。
        受信側で同じシークレットで再計算して一致を確認してください。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WebhookEvent'
      responses:
        '200':
          description: 受信成功 (Sonogo は応答ボディは見ません。2xx を返してください)
